Spring安全过滤器在不需要时执行

cvxl0en2  于 2023-09-29  发布在  Spring
关注(0)|答案(1)|浏览(93)

当用一个有效的body向/API/v1/auth/authenticate发出请求时,我的Postman会得到一个名为token的cookie,其值是一个jwt。令牌被设置为20分钟后过期,当它过期时,我用确切的body运行调用,这次使用cookie,它被拒绝,基本上说cookie过期了,这是真的。但是,这个端点不需要进行身份验证,正如我在安全配置文件中所建立的那样。这是怎么回事?
我还想补充的是,当在Postman中更改cookie的名称时,请求会被接受,并得到我的响应,沿着一个名为token的新cookie,当删除cookie时,它也会被接受。
AuthController:

@RestController
@RequestMapping("/api/v1/auth/")
@RequiredArgsConstructor
public class AuthenticationController {

    private final AuthenticationService authenticationService;

    @PostMapping("/register")
    public ResponseEntity<AuthenticationResponse> register(@RequestPart("user") UserSignUpDto user,
                                                         @RequestPart("inpFile") MultipartFile profilePicture) {
        return ResponseEntity.ok(authenticationService.register(user, profilePicture));
    }

    @PostMapping("/authenticate")
    public ResponseEntity<AuthenticationResponse> authenticate(@RequestBody UserLogInDto request,
                                                               HttpServletResponse response) {
        return ResponseEntity.ok(authenticationService.authenticate(request, response));
    }

    @ExceptionHandler(ResponseStatusException.class)
    public ResponseEntity<Exception> handleConflictError(ResponseStatusException exception) {
        // todo figure out ResponseStatusException
        return ResponseEntity.status(exception.getStatusCode()).body(exception);
    }

}

安全配置:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final AuthenticationProvider authProvider;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .cors(Customizer.withDefaults())
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> {
                   auth.requestMatchers("/api/v1/auth/**").permitAll();
                   auth.requestMatchers("/home/**").permitAll();
                   auth.requestMatchers("/user/**").permitAll();
                   auth.requestMatchers("/picture/**").permitAll();
                   auth.anyRequest().authenticated();
                })
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authenticationProvider(authProvider)
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("http://localhost:4200"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedMethods(List.of("GET", "POST"));
        configuration.setAllowedHeaders(List.of("Content-Type"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}

JwtAuthenticationFilter:

@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtService jwtService;
    private final UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal( // todo: ask ChatGPT to explain this
                                     @NonNull HttpServletRequest request,
                                     @NonNull HttpServletResponse response,
                                     @NonNull FilterChain filterChain
    ) throws ServletException, IOException {
        final String userEmail;
        final String jwt;
        final Cookie jwtCookie = request.getCookies() != null ?  Arrays.stream(request.getCookies()).filter(cookie -> cookie.getName().equals("token"))
                .findFirst()
                .orElse(null):  null;

        if (jwtCookie == null) {
            filterChain.doFilter(request, response);
            return;
        }

        jwt = jwtCookie.getValue();
        userEmail = jwtService.extractUsername(jwt);// todo extract the userEmail token;
        if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);

            if (jwtService.isTokenValid(jwt, userDetails)) {
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );

                authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }

        filterChain.doFilter(request, response);
    }

}
wj8zmpe1

wj8zmpe11#

看起来你的JwtAuthenticationFilter代码中的这一部分是相关的:

final Cookie jwtCookie = request.getCookies() != null ?  Arrays.stream(request.getCookies()).filter(cookie -> cookie.getName().equals("token"))
                .findFirst()
                .orElse(null):  null;

        if (jwtCookie == null) {
            filterChain.doFilter(request, response);
            return;
        }

请注意,如果您的cookie不使用该确切名称,则将跳过您的机制。检查您的SecurityConfiguration,过滤器存在于所有请求中,因此您需要实现一种机制来不将过滤器添加到这些不安全的端点,或者向过滤器添加一个方法覆盖,以便它不会在不安全的端点上激活:

@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
    // your implementation
}

一种方法是使用request.getRequestURI()

相关问题