允许Spring Security 6.1.1中进行身份验证的请求的CORS设置。

huangapple go评论223阅读模式
英文:

Allow CORS with Spring Security 6.1.1 with authenticated requests

问题

我已经升级了Spring Boot 2.5到3.1,其中包含Spring Security 6.1.1。调用登录身份验证REST服务正常工作,但所有需要身份验证令牌的其他REST控制器的请求都被CORS策略阻止。

我已经按照Spring文档中的指示禁用了CORS,但它不起作用。
https://docs.spring.io/spring-security/reference/reactive/integrations/cors.html#page-title

这是我当前的配置:

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOriginPattern("*");
        configuration.setAllowedMethods(Arrays.asList("GET","POST","PUT","PATCH","DELETE","OPTIONS"));
        configuration.setAllowCredentials(false);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                //.cors(cors -> cors.disable()) <<--- does not work as documented
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(request -> request
                    .requestMatchers("/api/auth/**").permitAll()
                    .requestMatchers(SYS_ADMIN_PATTERNS).hasAuthority("SYSTEM_ADMIN")
                    .requestMatchers("/api/v1/**").authenticated()
            )
            .sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS))
            .authenticationProvider(authenticationProvider())
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

我尝试过使用 .cors(cors -> cors.disable()) 禁用CORS,但它没有禁用CORS过滤。

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(cors -> cors.disable()) 
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(request -> request
                    .requestMatchers("/api/auth/**").permitAll()
                    .requestMatchers(SYS_ADMIN_PATTERNS).hasAuthority("SYSTEM_ADMIN")
                    .requestMatchers("/api/v1/**").authenticated()
            )
            .sessionManagement(manager -> manager.sessionCreationPolicy(STATELESS))
            .authenticationProvider(authenticationProvider())
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

我还尝试为REST控制器类添加了 @CrossOrigin 注解标签,但没有任何作用。还要确保我有 @Configuration 注解和 @EnableWebSecurity 注解(这是Spring Security的另一个更改)。

我漏掉了什么?

英文:

I've upgraded from Spring Boot 2.5 to 3.1, which comes with Spring Security 6.1.1. Calls to the login authentication REST service work just fine, but all requests to other REST controllers that require authentication token are being blocked by the CORS policy.

I have followed the directions in Springs documentation to disable CORS, but it does not work.
https://docs.spring.io/spring-security/reference/reactive/integrations/cors.html#page-title

Here is the current configuration that I have:

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOriginPattern(&quot;*&quot;);
        configuration.setAllowedMethods(Arrays.asList(&quot;GET&quot;,&quot;POST&quot;,&quot;PUT&quot;,&quot;PATCH&quot;,&quot;DELETE&quot;,&quot;OPTIONS&quot;));
        configuration.setAllowCredentials(false);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration(&quot;/**&quot;, configuration);
        return source;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(cors -&gt; cors.configurationSource(corsConfigurationSource()))
                //.cors(cors -&gt; cors.disable()) &lt;&lt;--- does not work as documented
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(request -&gt; request
                    .requestMatchers(&quot;/api/auth/**&quot;).permitAll()
                    .requestMatchers(SYS_ADMIN_PATTERNS).hasAuthority(&quot;SYSTEM_ADMIN&quot;)
                    .requestMatchers(&quot;/api/v1/**&quot;).authenticated()
            )
            .sessionManagement(manager -&gt; manager.sessionCreationPolicy(STATELESS))
            .authenticationProvider(authenticationProvider())
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

I have tried setting disabling the CORS using the .cors(cors -> cors.disable()), which did not disable CORS filtering.

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(cors -&gt; cors.disable()) 
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(request -&gt; request
                    .requestMatchers(&quot;/api/auth/**&quot;).permitAll()
                    .requestMatchers(SYS_ADMIN_PATTERNS).hasAuthority(&quot;SYSTEM_ADMIN&quot;)
                    .requestMatchers(&quot;/api/v1/**&quot;).authenticated()
            )
            .sessionManagement(manager -&gt; manager.sessionCreationPolicy(STATELESS))
            .authenticationProvider(authenticationProvider())
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

Also tried adding @CrossOrigin annotation tags to the REST controller classes, which did nothing. Also verified that I have the @Configuration annotation with the @EnableWebSecurity annotation (another change in Spring Security).

What am I missing?

答案1

得分: 1

以下是已翻译的部分:

唯一使其工作的方法是在SecurityFilterChain中禁用CORS,并在RestController上使用@CrossOrigin进行注释。如果已配置CorsConfigurationSource,则@CrossOrigin注释将被忽略(或至少没有效果),并且它在Spring Security 6.1中根本无法工作。

以下是工作配置:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .cors(AbstractHttpConfigurer::disable)
        .csrf(AbstractHttpConfigurer::disable)
        .authorizeHttpRequests(request -&gt; request
                .requestMatchers(&quot;/api/auth&quot;).permitAll()
                .requestMatchers(HttpMethod.OPTIONS).permitAll()
                .requestMatchers(SYS_ADMIN_PATTERNS).hasAuthority(&quot;SYSTEM_ADMIN&quot;)
                .requestMatchers(&quot;/api/v1/**&quot;).authenticated()
        )
        .sessionManagement(manager -&gt; manager.sessionCreationPolicy(STATELESS))
        .authenticationProvider(authenticationProvider())
        .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    ;
    SecurityFilterChain chain = http.build();
    log.info(&quot;Configured security filter chain: {}&quot;,chain);
    return chain;
}

然后,请确保在您的REST控制器上在类级别或个别方法级别添加@CrossOrigin注释。

@RestController
@RequestMapping(&quot;/api/auth&quot;)
@RequiredArgsConstructor
@CrossOrigin
public class AuthenticationController {
...
}
英文:

The only way I could get it to work is to disable CORS in the SecurityFilterChain and annotate the RestController with @CrossOrigin. If you have the CorsConfigurationSource configured the @CrossOrigin annotations are ignored (or at least have no effect) and it simply doesn't work with Spring Security 6.1.

Here is the working configuration:

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(AbstractHttpConfigurer::disable)
            .csrf(AbstractHttpConfigurer::disable)
            .authorizeHttpRequests(request -&gt; request
                    .requestMatchers(&quot;/api/auth&quot;).permitAll()
                    .requestMatchers(HttpMethod.OPTIONS).permitAll()
                    .requestMatchers(SYS_ADMIN_PATTERNS).hasAuthority(&quot;SYSTEM_ADMIN&quot;)
                    .requestMatchers(&quot;/api/v1/**&quot;).authenticated()
            )
            .sessionManagement(manager -&gt; manager.sessionCreationPolicy(STATELESS))
            .authenticationProvider(authenticationProvider())
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        ;
        SecurityFilterChain chain = http.build();
        log.info(&quot;Configured security filter chain: {}&quot;,chain);
        return chain;
    }

Then ensure you have the @CrossOrigin annotations on your REST controllers at the class level or individual method level.

@RestController
@RequestMapping(&quot;/api/auth&quot;)
@RequiredArgsConstructor
@CrossOrigin
public class AuthenticationController {
...
}

答案2

得分: 1

经过几天的努力,我得出了一些结论,比如这个工作原理。

在我的预检请求中,我遇到了401错误。

由于预检请求引起了问题,我遵循了文档中的代码,我添加了一个专门用于预检请求的requestMatcher:

.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()

并且在你的控制器类级别添加@CrossOrigin

英文:

After struggling for couple of days, I come to some conclusion, like how this is working.

I was facing a 401 error in my preflight request

I followed the documentation code since the preflight request was causing the problem, I added one more requestMather which is specifically for the preflight request

 .requestMatchers(HttpMethod.OPTIONS,&quot;/**&quot;).permitAll()

允许Spring Security 6.1.1中进行身份验证的请求的CORS设置。

and add @CrossOrigin to your controllers at class level

huangapple
  • 本文由 发表于 2023年7月14日 03:16:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76682586.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定