스프링 시큐리티 인 액션 9장 공부 이후 필터에 @Component
어노테이션을 걸고 Config 클래스에서 기본 인증 필터 위치에 등록했었다.
@Component // 여기가 문제
public class StaticKeyAuthenticationFilter implements Filter {
private String authorizationKey;
public StaticKeyAuthenticationFilter(@Value("${authorization.key}") String authorizationKey) {
this.authorizationKey = authorizationKey;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
var httpRequest = (HttpServletRequest) request;
var httpResponse = (HttpServletResponse) response;
String authentication = httpRequest.getHeader("Authorization");
if (authentication == null || !authentication.equals(authorizationKey)) {
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
filterChain.doFilter(request, response);
}
}
@Configuration
public class ProjectConfig {
private static final Logger log = LoggerFactory.getLogger(ProjectConfig.class);
private AuthenticationProviderService authenticationProvider;
@Autowired
public ProjectConfig(@Lazy AuthenticationProviderService authenticationProvider,
StaticKeyAuthenticationFilter staticKeyAuthenticationFilter) {
this.staticKeyAuthenticationFilter = staticKeyAuthenticationFilter;
this.authenticationProvider = authenticationProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
Map<String, PasswordEncoder> encoderMap = new HashMap<>();
encoderMap.put("bcrypt", new BCryptPasswordEncoder());
encoderMap.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
return new DelegatingPasswordEncoder("bcrypt", encoderMap);
}
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
**.addFilterAt(staticKeyAuthenticationFilter, BasicAuthenticationFilter.class)**
.authorizeHttpRequests(
request -> request.anyRequest()
.permitAll()
)
.csrf(Customizer.withDefaults());
return http.build();
}
}
10장을 공부하면서 다른 필터를 추가하게 되었고 이 과정에서 Config 클래스에서 addFilterAt()
메서드와 필드에서 StaticKeyAuthenticationFilter를 제거해줬다. 그 뒤 다른 필터를 테스트하였다.
책에서는 멀쩡하게 통신이 되었지만, 내 코드에서 추가한 필터는 동작하지만 HTTP 401 Unauthorized를 반환했다. 어디가 문제인지 하나씩 제거하다보니 @Component
가 문제인 것을 알게되었고 검색해보니 아래와 같은 내용이 있었다.
스프링 부트에 필터를 '조심해서' 사용하는 두 가지 방법
읽고 로깅해봤는데 아마 11단계에서 StaticKeyAuthenticationFilter가 호출되는 과정에서 Authorization
헤더가 없어 문제가 발생한 줄 알았다.
curl -v -H "Authorzation:auth_123" http://localhost:8080/hello
...
< HTTP/1.1 401
...
위와 같이 Authorization
헤더와 키값을 넣어줬는데도 401이 발생했다. 혹시나 해서 아래와 같이 이전에 사용했던 Request-Id
헤더도 추가해줬더니 정상적으로 응답이 온다.
curl -v -H "Authorization:auth_123" -H "Request-Id:12345" http://localhost:8080/hello
...
< HTTP/1.1 200
...
GET Hello!
하지만 작성된 Config 클래스에는 위의 두 필터를 등록하는 코드가 없다. 그럼에도 불구하고 영향을 미치고 있다.
@Configuration
public class ProjectConfig {
private static final Logger log = LoggerFactory.getLogger(ProjectConfig.class);
private AuthenticationProviderService authenticationProvider;
@Autowired
public ProjectConfig(@Lazy AuthenticationProviderService authenticationProvider) {
this.authenticationProvider = authenticationProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
Map<String, PasswordEncoder> encoderMap = new HashMap<>();
encoderMap.put("bcrypt", new BCryptPasswordEncoder());
encoderMap.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
return new DelegatingPasswordEncoder("bcrypt", encoderMap);
}
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// .authenticationProvider(authenticationProvider)
// .formLogin(
// customizer -> customizer
// .defaultSuccessUrl("/hello", true))
// .httpBasic(Customizer.withDefaults())
.addFilterAfter(new CsrfTokenLogger(), CsrfFilter.class)
.authorizeHttpRequests(
request -> request.anyRequest()
.permitAll()
)
.csrf(Customizer.withDefaults());
return http.build();
}
}
정확히 어떻게 돌아가는지는 잘 모르겠지만 @Component
어노테이션이 붙은 StaticKeyAuthenticationFilter
가 빈으로 등록되면서 RequestValidationFilter
역시 영향을 받아 함께 등록된 것 같다.
@Component
어노테이션을 제거하면 정상적으로 응답에 GET Hello!가 잘 도착한다.
curl -v http://localhost:8080/hello
...
< HTTP/1.1 200
...
GET Hello!
필터 클래스에 @Component
를 붙이는 것은 주의해야 할 것 같고, 필요없는 필터 클래스 역시 생성하지 않는 것이 좋을 것 같다.
'Today I Learned' 카테고리의 다른 글
Mermaid ERD 문법 (1) | 2024.12.02 |
---|---|
CSRF 토큰 확인 불가 문제 해결 (0) | 2024.06.29 |
@Default 빌더 기본값 적용 (0) | 2024.05.28 |