== maven (pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
== gradle (build.gradle)
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security'
SecurityConfig
라는 이름으로 클래스를 생성한다. 이는 사용자 정의 보안 클래스 용도이다.
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
@ConditionalOnDefaultWebSecurity
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class SecurityConfig{
@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER)
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated(); //모든 요청에 대해 인증을 하도록 하는 설정
htto
.formLogin(); // 스프링 시큐리티 로그인 방식을 폼로그인 방식으로 설정
return http.build();
}
}
스프링 시큐리티 버전이 올라가면서 설정 방법이 조금 바뀌었다. 기존에는 스프링 시큐리티의 WebSecurityConfigurerAdapter
를 상속받아 사용했었지만 이제 스프링은 이를 권장하지 않는다. 대신 SecurityFilterChain
을 사용하도록 권장한다. 사용방법은 위와 같은데 이때 주의할 점은 클래스 레벨에 @ConditionalOnDefaultWebSecurity
와 @ConditionalOnWebApplicaiton
어노테이션과 메소드 레벨에 @Order
어노테이션을 적용해야 한다는 것이다. 스프링 시큐리티 의존성을 주입하면 스프링이 자체적으로 SecurityFilterChain
의 빈을 생성해 놓기 때문에 그것과 충돌을 일으키지 않도록하는 설정인 것이다.
http.formLogin()
.loginPage("/login.html") // 사용자 정의 로그인 페이지
.defaultSuccessUrl("/home") // 로그인 성공 후 이동 페이지
.failureUrl("/login.html?error=true") // 로그인 실패 후 이동 페이지
.usernameParameter("username") // 아이디 파라미터명 설정
.passwordParameter("password") // 패스워드 파라미터명 설정
.loginProcessingUrl("/login") // 로그인 Form Action Url
.successHandler(loginSuccessHandler()) // 로그인 성공 후 핸들러
.failureHandler(loginFailureHandler()) // 로그인 실패 후 핸들러
formLogin()
에 대한 상세 설정 부분이다. 핸들러 부분은 익명 클래스를 사용해 좀더 세밀한 로직을 설정할 수 있다.
http.logout() // 로그아웃 처리
.logoutUrl("/logout") // 로그아웃 처리 URL
.logoutSuccessUrl("/login") // 로그아웃 성공 후 이동페이지
.deleteCookies("JSESSIONID“, "remember-me") // 로그아웃 후 쿠키 삭제
.addLogoutHandler(logoutHandler()) // 로그아웃 핸들러
.logoutSuccessHandler(logoutSuccessHandler()) // 로그아웃 성공 후 핸들러
http.rememberMe()
.rememberMeParameter(“remember”) // 기본 파라미터명은 remember-me
.tokenValiditySeconds(3600) // Default 는 14일
.alwaysRemember(true) // 리멤버 미 기능이 활성화되지 않아도 항상 실행
.userDetailsService(userDetailsService)
리멤버미는 자동 로그인 기능을 의미한다. 로그아웃을 통해 로그인에 대한 쿠키가 삭제되더라도 remember me 쿠키에 대한 Http 요청을 확인한 후 토큰 기반 인증을 사용해 유효성을 검사하고 로그인이 되는 방식이다.
Remember Me 설정을 하고나면 로그인 화면에 체크박스가 나타나는 걸 확인할 수 있다.
http.sessionManagement()
.maximumSessions(1) // 최대 허용 가능 세션 수 , -1 : 무제한 로그인 세션 허용
.maxSessionsPreventsLogin(true) // 동시 로그인 차단함, false : 기존 세션 만료(default)
.invalidSessionUrl("/invalid") // 세션이 유효하지 않을 때 이동 할 페이지
.expiredUrl("/expired ") // 세션이 만료된 경우 이동 할 페이지
사용자의 동시 접속을 제어하는 기능이다. 세션 허용 개수를 설정하고 만약 동시에 이 수를 초과하는 요청이 들어온다면 두 가지의 방법으로 이를 제어할 수 있다.
스프링 시큐리티는 세션 고정 공격에 대한 보안 기능을 제공한다.
세션이 고정적이라면 외부 공격에 대해 취약하기 때문에 이에 대한 기능을 기본적으로 제공한다.
http.sessionManagement()
.sessionFixation().changeSessionId() // 기본값
// none, migrateSession, newSession
요청이 생길 때 마다 세션을 생성하지만 세션의 설정 값은 그대로 적용해주는 changeSessionId()
가 기본값이고 none
은 세션을 고정하는 것이고 newSession
은 세션을 새로 생성하면서 설정값도 새로 만드는 것이다.
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy. If_Required )
권한 설정은 이후 진행될 실습에서 DB와 연동하여 자세하게 다룰 것이다.
RequestCache
를 이용해 인증 예외가 발생하기 전의 요청 정보를 저장한다. 예를 들어 비회원으로 장바구니로 이동했더니 인증이 되어있지 않아 로그인 페이지로 이동시켰지만 장바구니 페이지를 요청했던 것을 기억해 뒀다가 사용자가 로그인을 하고 나면 바로 장바구니로 이동할 수 있도록 하는 기능이다.
AccessDeniedHandler
에서 예외처리 하도록 제공
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint()) // 인증실패 시 처리
.accessDeniedHandler(accessDeniedHandler()) // 인증실패 시 처리