Я думаю, что не так, это мой фильтр аутентификации.
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
final String token = getTokenFromRequest(request);
final String username;
if (token == null) {
filterChain.doFilter(request, response);
return;
}
username = jwtService.getUsernameFromToken(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(token, userDetails)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
Сведения о пользователе добавляются в контекст безопасности, как и ожидалось, но затем doFilter все портит. Что я могу делать неправильно? Это SecurityConfig:
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final AuthenticationProvider authProvider;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf->
csrf.disable())
.authorizeHttpRequests(authRequest ->
authRequest
.requestMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(sessionManager ->
sessionManager.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authProvider)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}
Я всегда получаю ответ 403 Forbidden в Postman.
Есть идеи, что может быть не так?
Отлажено, но не могу найти проблему. Я что-то упустил (наверное, глупость), но не могу найти.
Заранее спасибо!
Обновлено: Это журналы с LogLevel DEBUG:
2024-07-01T11:50:08.830-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.security.web.FilterChainProxy : Securing POST /api/v1/demo/
Hibernate: select u1_0.id,u1_0.password,u1_0.role,u1_0.username from wluser u1_0 where u1_0.username=?
2024-07-01T11:50:33.405-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.security.web.FilterChainProxy : Secured POST /api/v1/demo/
2024-07-01T11:50:33.442-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.security.web.FilterChainProxy : Securing POST /error
2024-07-01T11:50:33.443-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.s.w.a.AnonymousAuthenticationFilter : Set SecurityContextHolder to anonymous SecurityContext
2024-07-01T11:50:33.444-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.s.w.a.Http403ForbiddenEntryPoint : Pre-authenticated entry point called. Rejecting access
журналы отладки показывают, что вы вызываете конечную точку без аутентификации — отсюда и значок 403
. Вам нужно пройти метод doFilterInternal
с отладчиком и посмотреть, почему не установлена аутентификация
@JAsgarov, оценивающий SecurityContextHolder, передает принципалу правильные данные от пользователя и аутентификацию = true в конце doFilterInternal. SessionId имеет значение null, но должно ли оно быть нулевым?
sessionId имеет значение null, поскольку вы установили сеанс без сохранения состояния SessionCreationPolicy.STATELESS
(нет сеанса). Но для аутентификации вам следует использовать какой-то заголовок/файл cookie токена jwt, а ваш jwtAuthenticationFilter
должен установить объект аутентификации.
Токен передается в запрос правильно, поскольку я правильно получаю все данные из токена, и также выполняется SecurityContextHolder.getContext().setAuthentication(authToken), поскольку в конце doFilterInternal SecurityContextHolder.getContext(). getAuthentication().isAuthenticated() оценивается как true. Я не там ищу?
пожалуйста, удалите весь JWTFilter, раздача JWT браузерам опасна, и есть причина, по которой это не встроено в систему безопасности Spring. Пожалуйста, не просто гуглите и читайте блог, читайте настоящую документацию и не используйте JWT там, для чего они не предназначены. Прочтите документы.
Этот вопрос похож на: Spring Boot 3 с исключениями Spring Security Intercepts. Я этого не хочу. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.
Вы получаете 403, потому что ваша конечная точка /error
не разрешена. Если вы откроете endpint, вы увидите настоящую причину.
@dur, спасибо, что указал на это, потому что это решило проблему. Я не знал, что это проблема с конечной точкой /error, поэтому не стал искать в этом направлении. Теперь мне интересно, почему отсутствие разрешения /error влияет на запрос, который не должен его выдавать.
Благодаря @dur я решил эту проблему!
Моя конечная точка /error была защищена, поэтому был получен ответ 403.
Добавление .requestMatchers("/error").permitAll()
в мою безопасностьFilterChain решило проблему.
Приносим извинения всем, кто видел вопрос, похожий на Spring Boot 3 с исключениями Spring Security Intercepts, я этого не хочу Честно говоря, я не знал, что это проблема, поэтому не проводил никаких исследований в этом направлении. Спасибо всем, кто потратил время на помощь!!
Теперь мне интересно, почему это происходит. Думаю, сейчас я проведу небольшое исследование по этому поводу.
Здравствуйте! Чтобы быть уверенным в отладчике, вы дошли до конца метода doFilterInternal и увидите, что для auth.isAuthenticated() установлено значение True? Вы также можете изменить безопасность Spring, чтобы получать больше журналов о цепочке фильтров, установив уровень журнала TRACE. Пример