본문 바로가기

세미나

실무에서 사용하는 Spring Security Configuration

728x90

안녕하세요. 유저인사이트 박태양입니다.

 

저희는 신규 프로젝트를 시작할때, SecurityConfig라는 클래스 안에 여러가지 보안 관련 코드를 구현합니다.

초기에 잘 작성된 코드이기에 특별한 수정 없이 사용하였지만,

간혹 해당 프로젝트에는 필요없는 코드도 섞여들어가는 경우도 있었습니다.

Spring Security 버전이 변경되면서, 이번 기회에 보안 관련 코드를 정리하는 시간을 가져보았습니다.

 


목차

  1. WebSecurityConfigureAdapter (deprecated)
  2. WebSecurity vs HttpSecurity
  3. HttpSecurity의 다양한 옵션들

1. WebSecurityConfigureAdapter (deprecated)

기존에는 WebSecurityConfigureAdapter를 상속받아 보안 관련 클래스를 구성하였습니다.

하지만, Spring Security 5.7.0-M2 부터 해당 클래스가 deprecated 되었기 때문에 새로운 방식이 필요합니다.

 

we encourage users to move towards a component-based security configuration.

 

스프링 공식 블로그에 나와있는 안내문입니다. 컴포넌트 기반으로 시큐리티를 설정하도록 유도하고 있습니다.

아래 코드처럼 SecurityFilterChain을 빈으로 등록하여주면 됩니다.

 

기존코드

더보기
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
    }

}

 

개선된코드 (SecurityFilterChain 빈 등록)

더보기
@Configuration
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
        return http.build();
    }

}

2. WebSecurity vs HttpSecurity

WebSecurity는 일반적으로 ignoring() 처리를 통해서

Spring Security에서 인증받지 않아도 되는 패턴이나 URL을 정의할때 사용합니다. (리소스 등)

반면에, HttpSecurity는 특정 URL에서 보안 인증을 받도록 설정할 수 있습니다.

 

기존코드

더보기
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/ignore1", "/ignore2");
    }

}

 

개선된코드

더보기
@Configuration
public class SecurityConfiguration {

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
    }

}

3. HttpSecurity의 다양한 옵션들

HttpSecurity 내에는 다양한 옵션들이 존재합니다.

 

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/attachment/**").permitAll()
        .antMatchers("/auth/**").anonymous()
        .anyRequest().authenticated();
    return http.build();
}

authorizeRequests는 URL 패턴을 통해 액세스를 제한할 수 있게 해줍니다.

/attachment/** 는 누구에게나 허용하고, /auth/** 는 익명 사용자에게만 허용합니다.

나머지 요청은 모두 인증을 받은 상태여야 접근이 가능합니다.

 

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.formLogin().loginPage(SpringSecurity.LOGIN_URL)
        .loginProcessingUrl(SpringSecurity.LOGIN_PROCESS_URL)
        .successHandler(customAuthenticationSuccessHandler())
        .failureHandler(customAuthenticationFailureHandler())
        .usernameParameter(SpringSecurity.PARAM_USERNAME)
        .passwordParameter(SpringSecurity.PARAM_PASSWORD);
    return http.build();
}

formLogin은 폼 기반 인증을 사용할 수 있도록 합니다.

파라미터로 들어가는 URL은 SpringSecurity 클래스에 상수로 지정해놓고 사용하였습니다.

로그인 성공 및 실패 시 제어를 위해 CustomAuthenticationHandler를 구현하였습니다.

 

@Bean
public AuthenticationFailureHandler customAuthenticationFailureHandler() {
  return new CustomAuthenticationHandler();
}

@Bean
public AuthenticationSuccessHandler customAuthenticationSuccessHandler() {
  return new CustomAuthenticationHandler();
}

위 폼 로그인 설정에 사용되는 파일들을 빈으로 등록하였습니다.

CustomAuthenticationHandler는 AuthenticationSuccessHandler, AuthenticationFailureHandler를 implments 하였습니다.

 

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.logout()
        .logoutRequestMatcher(new AntPathRequestMatcher(SpringSecurity.LOGOUT_URL))
        .logoutSuccessUrl(SpringSecurity.LOGIN_URL)
    return http.build();
}

로그아웃 요청 URL과 성공 시 이동하게 될 URL을 지정합니다.

 

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.exceptionHandling()
        .accessDeniedPage(SpringSecurity.LOGIN_SUCCESS_URL)
        .authenticationEntryPoint(ajaxAwareAuthenticationEntryPoint());
    return http.build();
}

접근 거절 시 이동하게 될 URL을 설정합니다.

 

@Bean
public LoginUrlAuthenticationEntryPoint ajaxAwareAuthenticationEntryPoint() {
  return new AjaxAwareAuthenticationEntryPoint(SpringSecurity.LOGIN_URL);
}

ajaxAwareAuthenticationEntryPoint는 세션이 만료된 상태에서 ajax 요청을 하지 못하도록 설정해주는 클래스입니다.

 

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.sessionManagement().maximumSessions(1)
    	.maxSessionsPreventsLogin(false)
        .expiredUrl(SpringSecurity.LOGIN_URL).and()
        .invalidSessionUrl(SpringSecurity.LOGIN_URL);
    return http.build();
}

세션 최대 갯수를 1개로 설정합니다.

새로운 사용자가 로그인을 한 경우 기존 사용자의 세션을 만료시키고 로그인 페이지로 돌려보냅니다.

 


이상으로 Spring Security 관련 Configuration을 알아보았습니다.

새로운 프로젝트를 시작하거나, 기존 프로젝트의 보안 관련 부분을 갱신할때 도움이 되었으면 좋겠습니다.

감사합니다.

 

참고자료 1 : https://spring.io/guides/gs/securing-web/

 

Spring | Home

Cloud Your code, any cloud—we’ve got you covered. Connect and scale your services, whatever your platform.

spring.io

참고자료 2 : https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter

 

Spring | Home

Cloud Your code, any cloud—we’ve got you covered. Connect and scale your services, whatever your platform.

spring.io

참고자료 3 : https://stackoverflow.com/questions/56388865/spring-security-configuration-httpsecurity-vs-websecurity

 

Spring Security Configuration - HttpSecurity vs WebSecurity

I just need to understand something in Spring Security Configuration. Using the example below... @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override

stackoverflow.com

 

728x90