简体   繁体   English

filterChain.doFilter 在 Spring 没有到达目的地

[英]filterChain.doFilter does not reach its destination in Spring

I have the following controller that creates a user based on the request body.我有以下 controller 根据请求正文创建用户。

    @PostMapping
    public void registerNewUser(@RequestBody User user) {
        userService.addNewUser(user);

    }

However I have also implemented a filter chain to validate the request's cookie, but since I am creating a user no cookies need to be validated.但是,我还实现了一个过滤器链来验证请求的 cookie,但由于我正在创建一个用户,因此不需要验证 cookies。 Therefore I have made the following if statement因此,我做了以下 if 语句

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

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

But this is where the issue occurs.但这就是问题发生的地方。 It does not reach its end destination (the controller) and create my user.它没有到达其最终目的地(控制器)并创建我的用户。 In fact it gives me a 403 Forbidden status code.事实上,它给了我一个 403 Forbidden 状态代码。 What am I missing?我错过了什么?

I suspect that my authentication filter might cause the issue.我怀疑我的身份验证过滤器可能会导致问题。 I believe it is trying to authenticate all incoming requests which I don't want for the registration endpoint.我相信它正在尝试验证我不想用于注册端点的所有传入请求。

public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        
        try {
            UsernameAndPasswordAuthenticationRequest authenticationRequest = new ObjectMapper().readValue(request.getInputStream(), UsernameAndPasswordAuthenticationRequest.class);
            Authentication authentication = new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword());
            Authentication authenticate = authenticationManager.authenticate(authentication);
            return authenticate;


        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {

        String token = Jwts.builder()
                .setSubject(authResult.getName())
                .claim("authorities", authResult.getAuthorities())
                .setIssuedAt(new Date())
                .setExpiration(java.sql.Date.valueOf(LocalDate.now().plusDays(jwtConfig.getTokenExpirationAfterDays())))
                .signWith(secretKey)
                .compact();


        response.resetBuffer();
        response.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
        response.getOutputStream().print(new ObjectMapper().writeValueAsString("Authenticated!"));
        Cookie sessionCookie = new Cookie("JSESSIONID", token);
        response.addCookie(sessionCookie);
        response.flushBuffer();

    }
}

My configuration我的配置

    protected void configure(HttpSecurity http) throws Exception {
        http.cors().configurationSource(corsConfigurationSource()).and().csrf().disable().formLogin().disable().httpBasic().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager(), jwtConfig, secretKey))
                .addFilterAfter(new JwtTokenVerifier(secretKey, jwtConfig), JwtUsernameAndPasswordAuthenticationFilter.class)
                .authorizeRequests().antMatchers("/", "index", "/css/*", "/js/*").permitAll().antMatchers("/api/**")
                .hasRole(ApplicationUserRole.USER.name()).anyRequest().authenticated();

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(daoAuthenticationProvider());
    }
@Bean
public CorsConfigurationSource corsConfigurationSource() {
    final CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
    configuration.setAllowedMethods(Arrays.asList("GET","POST", "OPTIONS", "PUT", "DELETE"));
    configuration.addAllowedHeader("Access-Control-Allow-Origin");
    configuration.addAllowedHeader("Content-Type");
    configuration.setAllowCredentials(true);
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setPasswordEncoder(passwordEncoder);
        provider.setUserDetailsService(applicationUserService);
        return provider;
    }

@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer{

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("http://localhost:3000").allowCredentials(true).allowedMethods("GET", "POST","PUT", "DELETE", "OPTIONS");


            }
        };
    }
}

Just an update:只是一个更新:

I have implemented a shouldnotfilter method to avoid filtering on registering, but the problem still persist.我已经实现了一个 shouldnotfilter 方法来避免在注册时进行过滤,但问题仍然存在。 I still receive 403 Forbidden but it seems like it does not filter on the registration endpoint我仍然收到 403 Forbidden 但它似乎没有在注册端点上进行过滤

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        String path = request.getRequestURI();
        return "/management/api/v1/users/register".equals(path);
    }

So the issue was actually in the configure method.所以问题实际上是在配置方法中。 I was actually allowing the specific endpoint to only role-specific users as following:我实际上只允许特定端点使用特定于角色的用户,如下所示:

.antMatchers("/api/**").hasRole(ApplicationUserRole.USER.name()).anyRequest().authenticated() .antMatchers("/api/**").hasRole(ApplicationUserRole.USER.name()).anyRequest().authenticated()

I missed this, as I was actually using /management/api/ but did not know this was applied and thought there was something wrong with my filter, but it was a security configuration issue.我错过了这个,因为我实际上是在使用 /management/api/ 但不知道它被应用了并且认为我的过滤器有问题,但这是一个安全配置问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM