Spring Security - 설정 (Spring Security 6.1)

Beomsu Son·2023년 5월 28일
7

설정


우리가 Spring Security를 우리의 애플리케이션에 맞게 사용하기 위해선 설정을 피할 수 없다.

그러기 위해서는 Filter Chain을 애플리케이션의 니즈에 맞게 설정하여 직접 등록해줘야만 한다.

💡 Filter Chain이란?
어떤 요청에 대해서 엔드 포인트에 도달하기 전에 요청을 가로채서 어떤 작업을 수행하는 컴포넌트를 “서블릿 필터(Servlet Filter)”라고 부른다.

주로 특정 URL 요청에 대한 보호나 인증 등에 대한 처리를 전처리하기 위해 사용한다고 생각하면 될 것 같다.

이러한 필터들이 Chain, 즉 사슬처럼 엮인 것을 Filter Chain이라고 부른다.

(이미지 출처: https://velog.io/@wnguswn7/Section4-3.-Spring-Security-Security-%EA%B8%B0%EB%B3%B82)

필터체인 내부의 필터들은 각각 doFilter()라는 메서드를 담고 있다. 필터에 해당하는 작업을 하고, 다음 필터로 넘어가는 것이다.

각각의 필터를 모두 통과한 이후에는 Dispatcher Servlet에 의해 적절한 Controller에 요청이 위임될 것이다.

@Configuration
@EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터체인에 등록이 됨.
public class SecurityConfig {
		@Bean
		public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
				return http
                // stateless한 rest api를 개발할 것이므로 csrf 공격에 대한 옵션은 꺼둔다.
 				.csrf(AbstractHttpConfigurer::disable)

				// 특정 URL에 대한 권한 설정.
                .authorizeHttpRequests((authorizeRequests) -> {
                    authorizeRequests.requestMatchers("/user/**").authenticated();

                    authorizeRequests.requestMatchers("/manager/**")
                            // ROLE_은 붙이면 안 된다. hasAnyRole()을 사용할 때 자동으로 ROLE_이 붙기 때문이다.
                            .hasAnyRole("ADMIN", "MANAGER");

                    authorizeRequests.requestMatchers("/admin/**")
                            // ROLE_은 붙이면 안 된다. hasRole()을 사용할 때 자동으로 ROLE_이 붙기 때문이다.
                            .hasRole("ADMIN");
                            
                    authorizeRequests.anyRequest().permitAll();
                })
                
                .formLogin((formLogin) -> {
                /* 권한이 필요한 요청은 해당 url로 리다이렉트 */
				    formLogin.loginPage("/login");
                })
                
                .build();
		}
}

이런 식으로 굉장히 간단한 필터 체인을 등록해봤다.
그 외에 다른 메서드들도 많이 있다. 이러한 메서드들은 다른 포스트에서 제대로 정리하겠다.

왜 기존의 다른 예제들과 다른 모습을 하고 있을까?


일단 WebSecurityConfigurerAdapter가 deprecated 되었다. 따라서 이를 상속하여 configure 함수를 오버라이딩 하는 식으로 개발하는 것이 아니라, 아예 자체적으로 SecurityFilterChain Bean을 생성하는 방식으로 바뀌었다.

Bean을 만들어 사용하는 방식을 제외하면 기존과 거의 동일하다. 기존 명세와 달라진 함수들이 몇몇 존재하는 데, 역할과 사용은 거의 동일하기 때문에 어떻게 사용해야 하는지만 찾아보면 될 듯하다.

++ 최근 Spring Security 6.1이 GA가 되면서 기존 함수들과 상당히 다른 모습을 가지게 되었다..

우선, 기존의 HttpSecurity 의 무분별한 메서드 체이닝을 지양하도록 바뀌었다.

    // 기존의 메서드 체이닝 방식
	.csrf().disable()

    .sessionManagement().sessionCreationPolicy(...)

    .and()
    .authorizeHttpRequests()
    // ...

코드를 보면 알겠지만, 기존에는 전혀 관계가 없는 요소들 끼리도 서로 직렬로 연결해서 사용했다. csrf와 disable은 관계가 있지만 sessionManagement와는 관계가 없다. 즉 다소 가독성이 떨어진다.

    // 수정된 메서드 체이닝 방식
	.csrf(이곳에 CSRF 설정을 위한 함수)

    .sessionManagement(이곳에 세션 설정을 위한 함수)

    .authorizeHttpRequests(이곳에 인가 설정을 위한 함수);

지금은 하나의 요소에 대한 건 하나의 메서드 안에서 처리하도록 바뀌었다.
csrf을 disable하고 싶으면 csrf 메서드 안에 disable과 관련된 람다함수를 넣어주는 식으로 바뀐 것이다.

이런 식으로 코딩하지 않으면 IDE에서 에러를 뱉어내므로 주의.

💡 구현 방식
어떤 식으로 구현해야 하는지는 IDE에서 각 메서드(csrf, authorizeHttpRequests 등등..)에 커서를 가져다대면 위 사진처럼 예제를 보여주기 때문에 구글링 하느라 괜히 진빼지는 말자.

개인적으로는 각 메서드들이 좀 더 알아보기 쉽게 변한 듯 하여 좋은 것 같다.

참고한 자료


[Section4] 3. [ Spring Security ] Security 기본 2

Spring Boot 3.1(Spring 6.1) Security Config: 'csrf()' is deprecated and marked for removal

profile
생각날 때마다 기록하기

1개의 댓글

comment-user-thumbnail
2023년 7월 7일

진짜 감사합니다 은인이십니다.. 댓글달려고 회원가입도 했습니다 감사합니다아

답글 달기