当前位置: 首页 > 知识库问答 >
问题:

Spring Boot permitAll not work in WebSecurityConfigrerAdapter

曹季同
2023-03-14

当我POST到/api/v1/auth/寄存器时,我会收到由配置的access DeniedHandler生成的403响应。但是,我希望这个请求是允许的,因为它由permitAll()覆盖,并且在anyRequest().身份验证()之前。

诸如GET /api/v1/reference/nations之类的请求工作正常。此外,我命中这些 /api/v1/auth/** 终结点的集成测试也可以正常工作,这表明与 CORS 有关,尽管预检请求为 200。

你知道这个安全配置有什么问题吗?

@Configuration
@EnableGlobalMethodSecurity(
    prePostEnabled = true,
    securedEnabled = true,
    jsr250Enabled = true
)
@Order(1)
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserDetailsServiceImpl userDetailsService;
    private final Config config;
    private final ObjectMapper objectMapper;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors()
            .and()

            .authorizeRequests()
            .antMatchers(
                "/api/v1/auth/register",
                "/api/v1/auth/register/check",
                "/api/v1/auth/register/activate",
                "/api/v1/auth/password/update",
                "/api/v1/auth/recover",
                "/api/v1/auth/recover/check",
                "/api/v1/auth/recover/reset",
                "/api/v1/csrf-token",
                "/api/v1/reference/**"
            )
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()

            .formLogin()
            .successHandler((request, response, authentication) -> {
                response.getWriter().append("OK");
                response.setStatus(HttpServletResponse.SC_OK);
            })
            .failureHandler((request, response, exception) -> {
                response.getWriter().append("Invalid credentials or inactive account");
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            })
            .loginProcessingUrl("/api/v1/auth/login")
            .permitAll()
            .and()

            .logout()
            .logoutRequestMatcher(new AntPathRequestMatcher("/api/v1/auth/logout", "POST"))
            .permitAll()
            .and()

            .exceptionHandling()
            .accessDeniedHandler((request, response, accessDeniedException) -> {
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                objectMapper.writeValue(
                    response.getWriter(),
                    ErrorResponseBody
                        .builder()
                        .code(ErrorType.ACCESS_DENIED)
                        .status(HttpServletResponse.SC_FORBIDDEN)
                        .message("Access denied")
                        .build()
                );
            })
            .authenticationEntryPoint((request, response, authException) -> {
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                objectMapper.writeValue(
                    response.getWriter(),
                    ErrorResponseBody
                        .builder()
                        .code(ErrorType.LOGIN_REQUIRED)
                        .status(HttpServletResponse.SC_UNAUTHORIZED)
                        .message("You are not authorized to access this resource")
                        .build()
                );
            })
            .and()

            .userDetailsService(userDetailsService);

        if (config.isCsrfDisabled()) {
            http
                .csrf()
                .disable();
        }
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final var configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedOrigins(config.getAllowedOrigins());
        configuration.setAllowedMethods(asList("GET", "POST", "PUT", "PATCH", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList(HttpHeaders.AUTHORIZATION, HttpHeaders.CACHE_CONTROL, HttpHeaders.CONTENT_TYPE, HttpHeaders.ACCEPT));
        final var source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/api/**", configuration);
        return source;
    }
}

这是我的CORS配置:

@Configuration
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WebConfig {
    private final Config config;

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                final var allowedOrigins = Optional
                    .ofNullable(config.getAllowedOrigins())
                    .map(origins -> origins.toArray(new String[]{}))
                    .orElse(new String[]{});

                System.out.println("Enabling CORS for the following origins:" + Arrays.asList(allowedOrigins).toString());

                registry
                    .addMapping("/api/**")
                    .allowedOrigins(allowedOrigins)
                    .allowCredentials(true)
                    .allowedMethods("*")
                    .allowedHeaders("*");
            }
        };
    }
}

我从http://localhost:3000调用这些endpoint,这是config.getAllowedOrigins()返回的项目之一。

以下是来自请求的Spring Security调试日志:

2020-11-24 06:51:16.110  INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-11-24 06:51:16.112  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-11-24 06:51:16.158  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 44 ms
2020-11-24 06:51:16.193 DEBUG 1 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-11-24 06:51:16.200 DEBUG 1 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-11-24 06:51:16.205 DEBUG 1 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2020-11-24 06:51:16.206 DEBUG 1 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2020-11-24 06:51:16.214 DEBUG 1 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-11-24 06:51:16.217 DEBUG 1 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 4 of 13 in additional filter chain; firing Filter: 'CorsFilter'
2020-11-24 06:51:16.286 DEBUG 1 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@461bbc94
2020-11-24 06:51:16.290 DEBUG 1 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2020-11-24 06:51:16.299 DEBUG 1 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2020-11-24 06:51:16.483 DEBUG 1 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 1 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-11-24 06:51:16.485 DEBUG 1 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 2 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-11-24 06:51:16.486 DEBUG 1 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2020-11-24 06:51:16.487 DEBUG 1 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2020-11-24 06:51:16.488 DEBUG 1 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 3 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-11-24 06:51:16.489 DEBUG 1 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 4 of 13 in additional filter chain; firing Filter: 'CorsFilter'
2020-11-24 06:51:16.494 DEBUG 1 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : /api/v1/auth/register at position 5 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
2020-11-24 06:51:16.525 DEBUG 1 --- [nio-8080-exec-2] o.s.security.web.csrf.CsrfFilter         : Invalid CSRF token found for http://dev.api.example.com/api/v1/auth/register
2020-11-24 06:51:16.609 DEBUG 1 --- [nio-8080-exec-2] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@461bbc94
2020-11-24 06:51:16.610 DEBUG 1 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2020-11-24 06:51:16.615 DEBUG 1 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

共有1个答案

蔚学真
2023-03-14

使用< code >禁用CSRF。csrf()。在< code >配置(HttpSecurity http)中的disable()更多细节在此解释

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
           .csrf().disable()
           ... // other configurations
}
 类似资料:

相关问答

相关文章

相关阅读