Spring Security의 Configure method를 아래와 같이 작성했으나,
.antMatchers("/api/login", "/api/signup", "/resources/**").permitAll() 설정을 했음에도 불구하고 로그인을 시도할때마다 계속 JwtFilter를 타고 있었다.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler)
.and()
.authorizeRequests() // 인증이 필요한 URL 패턴을 설정
.antMatchers("/api/login", "/api/signup", "/resources/**").permitAll() // 모두 접근 가능
.anyRequest().authenticated() // 나머지 URL은 모두 인증이 필요
.and()
.addFilterBefore(new JwtFilter(tokenProvider), UsernamePasswordAuthenticationFilter.class);
// JWT를 사용하여 인증하는 필터 추가
}
Security 설정에서 특정 url이 필터를 타지 않게 하려면 이 방법을 사용한다고 했지만, 이 코드는 특정 url이 필터를 타지 않도록 하는 게 아니었다. 검색해보니 이 부분을 헷갈리시는 분이 많은 것 같당. 저 포함 ㅎㅎ
https://stackoverflow.com/questions/46068433/spring-security-with-filters-permitall-not-working
이 글에서 확인할 수 있는 것처럼, permitAll()은 해당 요청에 대한 접근을 모든 사용자에게 허용하는 역할을 하지만, 요청 처리 과정에서 적용되는 모든 필터들을 무시하지는 않는다.
그저 해당 요청에 대한 인증 정보가 없더라도 (모든 필터를 처리한 후에도 SecurityContext에 인증 정보가 없더라도), 접근이 허용된다는 것을 의미한다.
따라서 filter 구성 중 특정 조건에서 Exception을 던지는 부분이 있다면, permitALl()을 한 것과는 상관 없이 에러가 잡히게 된다.
나와 같은 경우에는
String jwt = resolveToken(request);
private String resolveToken(HttpServletRequest request) {
String token = request.getHeader(AUTHORIZATION);
if (StringUtils.hasText(token) && token.startsWith(BEARER_PREFIX)) {
return token.substring(7);
}
throw new RuntimeException();
}
이 부분에서 RuntimeException()을 던지기 때문에 여기서 걸릴 수 밖에 없던 것이다.
보통 JWT과 같은 인증 filter단에서는 직접 에러를 던지지않으며, 401 또는 403과 같은 인증 및 권한 관련 에러는
.authenticationEntryPoint(jwtAuthenticationEntryPoint) // 인증 실패시 호출될 Entry Point 설정
.accessDeniedHandler(jwtAccessDeniedHandler) // 접근 권한이 없는 경우 호출될 Access Denied Handler 설정
이렇게 직접 에러 처리를 추가해줌으로써 가능해진다.
필터를 아예 거치지 않고 호출하지 않기 위해서는,
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/api/login", "/api/signup", "/resources/**");
}
이 방식이 더 적합하다.
하지만 스프링에서는 Warn을 통해 아래와 같이 permitAll()을 사용할 것을 권장한다.
You are asking Spring Security to ignore Ant [pattern='/api/signup']. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.