У меня несколько точек входа. Один из них должен быть защищен фильтром, остальные полностью открыты.
/data/** - filter protected
/callback/** - permitAll
/save/** - permitAll
/oauth/** - permitAll
В моем приложении отсутствуют пользователи, роли и база данных. Мне нужно только проверить JWT, что он подписан с правильным закрытым ключом. Итак, я использую:
@SpringBootApplication(exclude= {UserDetailsServiceAutoConfiguration.class})
Перепробовал множество комбинаций, либо требует от всех проверять JWT на все входные точки с помощью фильтра, либо 401 ошибка. Установлена анонимная роль, поскольку при установке .authenticated() возникла ошибка 403.
Пожалуйста помогите мне..
Мой адаптер конфигурации:
@EnableWebSecurity
public class DataSecurity extends WebSecurityConfigurerAdapter {
@Bean
public JwtAuthFilter jwtAuthenticationFilter() {
return new JwtAuthFilter();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.csrf().disable()
.httpBasic().disable()
.logout().disable()
.formLogin().disable()
.authorizeRequests().antMatchers("/data/**").hasAuthority("ROLE_ANONYMOUS")
.and()
.addFilterBefore(jwtAuthenticationFilter(), AuthorizationFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.anyRequest().permitAll();
}
@Override
public void configure(WebSecurity web){
web.ignoring().antMatchers("/oauth/**","/callback/**","/save/**");
}
}
Мой фильтр:
@Order(Ordered.HIGHEST_PRECEDENCE)
public class JwtAuthFilter extends OncePerRequestFilter {
@Value("${auth-service.secret-key}")
private String jwtSecret;
private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthFilter.class);
@Override
protected void doFilterInternal(
@Nullable HttpServletRequest request,
@Nullable HttpServletResponse response,
@Nullable FilterChain filterChain
)
throws IOException, ServletException {
assert request != null;
String jwt = parseJwt(request);
if (jwt!=null && validateToken(jwt) ) {
assert filterChain != null;
filterChain.doFilter(request, response);
} else {
assert response != null;
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7);
}
return null;
}
private boolean validateToken(String authToken) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
LOGGER.error("Error: {}", e.getMessage());
} catch (MalformedJwtException e) {
LOGGER.error("Error: {}", e.getMessage());
} catch (ExpiredJwtException e) {
LOGGER.error("Error: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
LOGGER.error("Error: {}", e.getMessage());
} catch (IllegalArgumentException e) {
LOGGER.error("Error: {}", e.getMessage());
}
return false;
}
}
Позвоните http://localhost:9088/oauth/test
Ответ:
{
"timestamp": "2023-03-30T07:52:22.692+00:00",
"status": 401,
"error": "Unauthorized",
"path": "/oauth/test"
}
СЛЕД:
2023-03-30 11:52:22.662 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Ant [pattern='/oauth/**'], Filters=[]] (1/3)
2023-03-30 11:52:22.662 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=Ant [pattern='/callback/**'], Filters=[]] (2/3)
2023-03-30 11:52:22.663 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@6e807e2, org.springframework.security.web.context.SecurityContextPersistenceFilter@7767bd4e, org.springframework.security.web.header.HeaderWriterFilter@1537e43, org.springframework.web.filter.CorsFilter@6c995c5d, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@433ef204, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@165614f5, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@203b953c, org.springframework.security.web.session.SessionManagementFilter@1304e0d7, org.springframework.security.web.access.ExceptionTranslationFilter@9a9aa68, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@389a5022, com.test.authorization.configuration.security.JwtAuthFilter@1fdca564]] (3/3)
2023-03-30 11:52:22.663 DEBUG 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Securing GET /error
2023-03-30 11:52:22.664 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking WebAsyncManagerIntegrationFilter (1/11)
2023-03-30 11:52:22.664 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking SecurityContextPersistenceFilter (2/11)
2023-03-30 11:52:22.665 DEBUG 6744 --- [nio-9092-exec-2] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
2023-03-30 11:52:22.665 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking HeaderWriterFilter (3/11)
2023-03-30 11:52:22.665 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking CorsFilter (4/11)
2023-03-30 11:52:22.665 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking RequestCacheAwareFilter (5/11)
2023-03-30 11:52:22.665 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking SecurityContextHolderAwareRequestFilter (6/11)
2023-03-30 11:52:22.666 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking AnonymousAuthenticationFilter (7/11)
2023-03-30 11:52:22.667 TRACE 6744 --- [nio-9092-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]
2023-03-30 11:52:22.667 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking SessionManagementFilter (8/11)
2023-03-30 11:52:22.667 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking ExceptionTranslationFilter (9/11)
2023-03-30 11:52:22.667 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking FilterSecurityInterceptor (10/11)
2023-03-30 11:52:22.668 TRACE 6744 --- [nio-9092-exec-2] edFilterInvocationSecurityMetadataSource : Did not match request to Ant [pattern='/data/**'] - [hasAuthority('ROLE_ANONYMOUS')] (1/2)
2023-03-30 11:52:22.668 TRACE 6744 --- [nio-9092-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Did not re-authenticate AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]] before authorizing
2023-03-30 11:52:22.668 TRACE 6744 --- [nio-9092-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Authorizing filter invocation [GET /error] with attributes [permitAll]
2023-03-30 11:52:22.672 DEBUG 6744 --- [nio-9092-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Authorized filter invocation [GET /error] with attributes [permitAll]
2023-03-30 11:52:22.672 TRACE 6744 --- [nio-9092-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Did not switch RunAs authentication since RunAsManager returned null
2023-03-30 11:52:22.672 TRACE 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Invoking JwtAuthFilter (11/11)
2023-03-30 11:52:22.673 DEBUG 6744 --- [nio-9092-exec-2] o.s.security.web.FilterChainProxy : Secured GET /error
2023-03-30 11:52:22.676 TRACE 6744 --- [nio-9092-exec-2] edFilterInvocationSecurityMetadataSource : Did not match request to Ant [pattern='/data/**'] - [hasAuthority('ROLE_ANONYMOUS')] (1/2)
2023-03-30 11:52:22.732 DEBUG 6744 --- [nio-9092-exec-2] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
мне просто нужно закрыть /data/** , остальные открыты.
@Yeras_QazaQ У меня все открыто для определенных конечных точек. И csrf отключен
В настоящее время ваш фильтр всегда выполняется, даже до неаутентифицированных вызовов.
Чтобы решить эту проблему, вы должны указать, какой запрос обрабатывать вашим фильтром. Для этого у вас есть два варианта:
добавьте метод shouldNotFilter
в свой JwtAuthFilter
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return !request.getRequestURI().startsWith("/data/");
}
просто добавьте следующее условие if в начало вашего JwtAuthFilter.doFilterInternal
:
if (!request.getRequestURI().startsWith("/data/")) {
filterChain.doFilter(request, response);
return;
}
Точно такая же проблема обсуждалась в следующем видео с отметкой времени 1:11:11: Безопасность Spring, демистифицированная Даниэлем Гарнье Муару
Вы можете добавить разрешение на конкретный адрес, например .antMatchers("/api/public").permitAll(), или попытаться отключить csrf для HttpSecurity, например .csrf().disable();