대부분의 애플리케이션에서는 회원관리를 하고 있고, 그에 따른 인증(Authentication)과 인가(Authorization)에 대한 처리를 해주어야 한다. Spring에서는 Spring Security라는 별도의 하위 프레임워크를 제공하고 있다.
Spring Security란?
- Spring기반 애플리케이션의 보안을 담당하는 스프링 하위 프레임워크
- Spring Security는 '인증(Authentication)'과 '권한(Authorization)'에 대한 부분을 Filter의 흐름에 따라 처리를 하고 있다.
- spring security는 filter 기반으로 동작하기 때문에 spring MVC 와 분리되어 관리 및 동작한다
> 보안관련 용어 정리
- 접근 주체(Principal) : 보호된 대상에 접근하는 유저
- 인증(Authenticate) : 현재 유저가 누구인지 확인(ex. 로그인)
- 애플리케이션의 작업을 수행할 수 있는 주체임을 증명 - 인가(Authorize) : 현재 유저가 어떤 서비스, 페이지에 접근할 수 있는 권한이 있는지 검사
- 권한 : 인증된 주체가 애플리케이션의 동작을 수행할 수 있도록 허락되있는지를 결정
- 권한 승인이 필요한 부분으로 접근하려면 인증 과정을 통해 주체가 증명 되어야만 한다
- 권한 부여에도 두가지 영역이 존재하는데 웹 요청 권한, 메소드 호출 및 도메인 인스턴스에 대한 접근 권한 부여
Spring Security는 기본적으로 인증 절차를 건친 후에 인가 절차를 진행하게 되며, 인가 과정에서 해당 리소스에 대한 접근 권한이 있는지 확인하게 된다.
Spring Security 구조
Spring Security는 세션-쿠키방식으로 인증한다.
1. 유저가 로그인을 시도 (http request)
2. AuthenticationFilter 에서부터 위와같이 user DB까지 타고 들어감
3. DB에 있는 유저라면 UserDetails 로 꺼내서 유저의 session 생성
4. spring security의 인메모리 세션저장소인 SecurityContextHolder 에 저장
5. 유저에게 session ID와 함께 응답을 내려줌
6. 이후 요청에서는 요청쿠키에서 JSESSIONID를 까봐서 검증 후 유효하면 Authentication를 쥐어준다.
프로젝트 구성 및 의존성 추가
Maven - pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Gradle - build.gradle
implementation 'org.springframework.boot:spring-boot-starter-security'
SecurityConfig 설정
SecurityConfig 설정 클래스를 생성하여 인증&인가 API를 만들어서 보안성을 높힐 수 있다.
package com.GStagram.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity // 해당 파일로 시큐리티를 활성화
@Configuration // IoC
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// super 삭제 - 기존 시큐리티가 가지고 있는 기능이 다 비활성화됨
// super.configure(http);
http.authorizeRequests()
.antMatchers("/","/user/**","/image/**","/subscribe/**","/comment/**")
.authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/auth/signin")
.defaultSuccessUrl("/");
}
}