JwtAuthFilter 适用于所有请求,甚至适用于允许的端点

问题描述 投票:0回答:1

我在使用新的 Spring Security 配置时遇到一些问题。我使用的是 Spring Boot 版本 3.1.4 和 Spring Security 版本 6.1.4。 在配置文件中,我定义某些页面无需身份验证即可访问。之后,我将 JwtAuthFilter 添加到链中。然而它总是被称为。即使对于应该允许的端点也是如此。例如,允许在没有身份验证的情况下访问因 403 错误而调用的错误页面。不幸的是,它还尝试通过 jwtAuthfilter 进行身份验证,这会导致另一个 403 错误,从而导致身份验证循环。我该如何解决这个问题? 这是我的配置和过滤器。

    @Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig {

 private final JwtAuthFilter jwtAuthFilter;
    private final UserProfileRepository userProfileRepository;

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http.authorizeHttpRequests(auth -> {
                    auth.requestMatchers("/").permitAll();
                    auth.requestMatchers("/login").permitAll();
                    auth.requestMatchers("/register").permitAll();
                    auth.requestMatchers("/error/**").permitAll();
                })
                .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authenticationProvider(authenticationProvider())
                .addFilterAfter(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return username -> {
            RegisteredUser registeredUser = userProfileRepository.findByMail(Email.of(username));
            if (registeredUser == null) {
                throw new UsernameNotFoundException("User not found");
            }
            return registeredUser;
        };
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService());
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager(UserDetailsService userDetailsService,
                                                       PasswordEncoder passwordEncoder) {
        return authentication -> {
            UserDetails user = userDetailsService.loadUserByUsername(authentication.getName());
            if (passwordEncoder.matches(authentication.getCredentials().toString(), user.getPassword())) {
                return new UsernamePasswordAuthenticationToken(
                        user.getUsername(),
                        user.getPassword(),
                        user.getAuthorities());
            }
            throw new BadCredentialsException("Bad Password");
        };
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12);
    } //TODO read from properties

}

这是我的过滤器

@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {

    private final JwtService jwtService;
    private final UserProfileRepository userProfileRepository;

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request,
                                    @NonNull HttpServletResponse response,
                                    @NonNull FilterChain filterChain) throws ServletException, IOException {

        final Cookie[] cookies = request.getCookies();

        if (cookies == null || cookies.length == 0) {
            filterChain.doFilter(request, response);
            return;
        }

        Optional<Cookie> authorizationCookie = Arrays.stream(cookies)
                .filter(cookie -> cookie.getName().equals("Authorization"))
                .findFirst();

        if (authorizationCookie.isEmpty()) {
            filterChain.doFilter(request, response);
            return;
        }

        String token = authorizationCookie.get().getValue();
        String mail = jwtService.extractMail(token);
        if (mail == null) {
            filterChain.doFilter(request, response);
            return;
        }

        SecurityContext context = SecurityContextHolder.getContext();
        if (context.getAuthentication() != null) {
            filterChain.doFilter(request, response);
            return;
        }

        RegisteredUser user = userProfileRepository.findByMail(Email.of(mail));
        if (user == null) {
            filterChain.doFilter(request, response);
            return;
        }

        if (jwtService.isTokenValid(token, user)) {
            var authenticationToken = new UsernamePasswordAuthenticationToken(
                    user,
                    null,
                    user.getAuthorities());
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            context.setAuthentication(authenticationToken);
        }
        filterChain.doFilter(request, response);
    }
}
java spring spring-boot spring-security jwt
1个回答
0
投票

将为每个请求调用您的过滤器,除非且直到您使用不同的基本路由创建单独的

SecurityFilterChain
。您可以添加检查以绕过过滤器中的特定路由:

if (request.getRequestURI().contains("/login") || request.getRequestURI().contains("/register")) {
 
    filterChain.doFilter(request, response);

}
© www.soinside.com 2019 - 2024. All rights reserved.