【问题标题】:Why CORS is not working with Spring Security 6?为什么 CORS 不能与 Spring Security 6 一起使用?
【发布时间】:2023-01-30 15:49:10
【问题描述】:

我尝试使用@ch4mp 的回答来应用 CORS 配置:Use Keycloak Spring Adapter with Spring Boot 3

并且还遵循了这里的指南: https://docs.spring.io/spring-security/reference/servlet/integrations/cors.html

问题是,当我检查它时,我在响应中看不到 CORS 标头,如下所示:https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-test-cors.html

我想在全球范围内配置 CORS,我们将不胜感激。

@Configuration
@EnableWebSecurity
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SecurityConfig {

    @Value("${eval.required.role.name}")
    private String requiredRoleName;


    @Bean
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, KeycloakLogoutHandler keycloakLogoutHandler, Jwt2AuthenticationConverter authenticationConverter, ServerProperties serverProperties) throws Exception {

        // If SSL enabled, disable http (https only)
        if (serverProperties.getSsl() != null && serverProperties.getSsl().isEnabled()) {
            http.requiresChannel().anyRequest().requiresSecure();
        } else {
            http.requiresChannel().anyRequest().requiresInsecure();
        }

        CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
        XorCsrfTokenRequestAttributeHandler delegate = new XorCsrfTokenRequestAttributeHandler();
        delegate.setCsrfRequestAttributeName("_csrf");

        CsrfTokenRequestHandler requestHandler = delegate::handle;

        http.cors(withDefaults());

        http.authorizeRequests(auth -> {
            auth.requestMatchers("/**").hasAuthority(requiredRoleName);
            auth.anyRequest().fullyAuthenticated();
        });

        http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(authenticationConverter);

        http.oauth2Login()
                .and()
                .logout()
                .addLogoutHandler(keycloakLogoutHandler)
                .logoutSuccessUrl("/");

        http.csrf(csrf -> csrf
                .csrfTokenRepository(tokenRepository)
                .csrfTokenRequestHandler(requestHandler));

        return http.build();
    }

    @Bean
    public Jwt2AuthoritiesConverter authoritiesConverter() {
        // This is a converter for roles, as embedded in the JWT by a Keycloak server
        return jwt -> {
            final var realmAccess = (Map<String, Object>) jwt.getClaims().getOrDefault("realm_access", Map.of());
            final var realmRoles = (Collection<String>) realmAccess.getOrDefault("roles", List.of());

            return realmRoles.stream().map(SimpleGrantedAuthority::new).toList();
        };
    }

    @Bean
    public Jwt2AuthenticationConverter authenticationConverter(Jwt2AuthoritiesConverter authoritiesConverter) {
        return jwt -> new JwtAuthenticationToken(jwt, authoritiesConverter.convert(jwt));
    }

    public interface Jwt2AuthoritiesConverter extends Converter<Jwt, Collection<? extends GrantedAuthority>> {
    }

    public interface Jwt2AuthenticationConverter extends Converter<Jwt, AbstractAuthenticationToken> {
    }



}


}

以及 CORS 配置:

@Component
public class CustomCorsConfiguration {

    @Value("${eval.cors.origin}")//*
    private String corsOrigin;

    @Value("${eval.cors.methods}")//"GET", "POST", "DELETE", "PUT", "OPTIONS"
    private List<String> corsMethods

    @Value("${eval.cors.header}")//*
    private String corsHeaders;

    @Value("${eval.cors.credentials}")//true
    private boolean corsCredentials;

    @Value("${eval.cors.maxAge}")//180
    private Long corsMaxAge;

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList(corsOrigin));
        configuration.setAllowedMethods(corsMethods);
        configuration.setAllowedHeaders(Arrays.asList(corsHeaders));
        configuration.setAllowCredentials(corsCredentials);
        configuration.setMaxAge(corsMaxAge);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }

}

【问题讨论】:

  • 在投票时也写评论会很好,这样也许下次我不会重蹈覆辙。
  • 对于初学者,请仔细阅读答案并按照说明进行操作。
  • 并且可能阅读您自己提供的链接 - AWS 文档说也要发送“OPTIONS”

标签: java spring-boot spring-security cors


【解决方案1】:

如何检查 CORS 是否与 Spring Boot 3 一起工作?

OPTIONS 请求发送到感兴趣的端点并检查是否存在所需的标头

【讨论】:

  • 我在我的问题中添加了一张图片。我发送了一个 Get 请求,但没有看到任何 CORS 标头
  • 就像我写的那样,发送OPTIONS而不是GET
  • 甚至你引用的 AWS 链接也说你应该发送选项......
  • 谢谢,我认为类型无关紧要。对不起,如果我让你生气了。我写在这里,因为我显然还在学习。我用邮递员发送了一个 OPTIONS 请求,但仍然没有看到那些标题...更新了图片
猜你喜欢
  • 2021-12-09
  • 2012-01-30
  • 2014-01-18
  • 2019-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多