如何在 Spring Boot + Spring Security 应用程序中配置 CORS?

Posted

技术标签:

【中文标题】如何在 Spring Boot + Spring Security 应用程序中配置 CORS?【英文标题】:How to configure CORS in a Spring Boot + Spring Security application? 【发布时间】:2016-08-26 10:08:39 【问题描述】:

我使用带有 Spring Security 和 Cors 支持的 Spring Boot。

如果我执行以下代码

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
    if xmlhttp.readyState is 4
        console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:a'
do xmlhttp.send

我得到了结果

200

如果我使用错误的凭据进行测试,例如

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
    if xmlhttp.readyState is 4
        console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:aa'
do xmlhttp.send

我得到的不是 401(这是 Spring Security 中错误身份验证的标准代码)

0

带有以下浏览器通知:

获取http://localhost:5000/api/token

XMLHttpRequest 无法加载 http://localhost:5000。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost:3000' 不允许访问。响应的 HTTP 状态代码为 401。

我正在开发前端代码,需要来自服务器响应的有用 http 状态代码来处理这种情况。我需要比 0 更有用的东西。响应正文也是空的。我不知道我的配置是错误的,还是软件错误,我也不知道是铬(使用arch linux)还是弹簧安全。

我的 Spring 配置是:

@SpringBootApplication
public class Application 
    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    


@RestController
@RequestMapping("api")
public class Controller 
    @RequestMapping("token")
    @CrossOrigin
    Map<String, String> token(HttpSession session) 
        return Collections.singletonMap("token", session.getId());
    


@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter 
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.inMemoryAuthentication().withUser("a").password("a").roles("USER");
    
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .anyRequest().authenticated()
                .and().httpBasic();
    

如果我用 curl 测试一切正常,我认为因为不需要 CORS 支持,但我尝试使用 OPTION 请求模拟 CORS,结果也可以。

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTpha"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTpha
> 
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Access-Control-Allow-Origin: http://localhost:3000
< Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE
< Access-Control-Max-Age: 3600
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Origin,Accept,X-Requested-    With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization
< x-auth-token: 58e4cca9-7719-46c8-9180-2fc16aec8dff
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:15:44 GMT
< 
* Connection #0 to host localhost left intact
"token":"58e4cca9-7719-46c8-9180-2fc16aec8dff"

并且凭据错误:

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTp"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTp
> 
< HTTP/1.1 401 Unauthorized
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< WWW-Authenticate: Basic realm="Realm"
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:16:15 GMT
< 
* Connection #0 to host localhost left intact
"timestamp":1462119375041,"status":401,"error":"Unauthorized","message":"Failed to decode basic authentication token","path":"/api/token"

编辑: 以免产生误会。我使用 1.3.3 Spring Boot。 博客文章写道:

CORS 支持将在即将发布的 Spring Boot 1.3 版本中提供,并且已经在 1.3.0.BUILD-SNAPSHOT 版本中提供。

在 Spring Boot 应用程序中使用带有 @CrossOrigin 注解的控制器方法 CORS 配置不需要任何特定配置。

可以通过使用自定义的 addCorsMappings(CorsRegistry) 方法注册 WebMvcConfigurer bean 来定义全局 CORS 配置:

我添加了以下代码以启用全局 cors 支持。实际上我以前试过这个,但结果是一样的。我最近又试了一次,结果还是一样。

@Configuration
public class MyConfiguration 

    @Bean
    public WebMvcConfigurer corsConfigurer() 
        return new WebMvcConfigurerAdapter() 
            @Override
            public void addCorsMappings(CorsRegistry registry) 
                registry.addMapping("/**");
            
        ;
    

虽然问题来自授权过程之间的重定向,但这个想法很有趣。如何更改重定向到任何资源以避免这种冲突?

编辑:

我想我离解决方案更近了。我已经使用支持 cors 的 nodejs 服务器进行了测试,通过添加 访问控制允许来源:* 对所有请求。

就像 Stefan Isele 已经提到的,似乎 spring 安全重定向或不添加 CORS 标头,所以这就是请求似乎被破坏的原因。因此,当 Spring Security 检查身份验证时,它必须添加正确的标头。

有人知道怎么做吗?

编辑:

我找到了一种解决方法,这似乎很难看。我已经为 Spring Boot 启动了一个 github 问题,我在其中描述了解决方法:https://github.com/spring-projects/spring-boot/issues/5834

【问题讨论】:

***.com/a/35040051/2884309 它是否也适用于 PUT 请求,或者我们必须单独定义它。默认情况下,所有来源和 GET、HEAD 和 POST 方法都是允许的。来自 Spring 文档 ^^ 【参考方案1】:
@Configuration
public class CorsConfig implements WebMvcConfigurer 
    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowCredentials(true);
    


截至 2021 年,这可能是最简单的解决方案,只需要创建一个单独的类。

就是这样。

【讨论】:

【参考方案2】:

如何在 Spring Boot 2.3+ 上解决 CORS

总结

如果您遇到此 CORS 问题,请不要担心。这是每个后端开发人员首次尝试与前端微服务集成时的常见问题。这是浏览器为了用户安全而严格应用的某种安全策略,这就是为什么当您通过 Postman/Swagger 或 cURL 尝试您的 API 时不会面对它的原因。

解决方案

客户端绕过(仅限开发人员)

以下解决方案仅用于开发目的,您绝对需要为您的生产环境永久解决此 CORS 问题。您可以使用以下浏览器扩展来绕过浏览器策略以解决 CORS 错误,但如果它们不能正常工作,请不要感到惊讶。

    CORS 解锁 Firefox - Chrome CORS 无处不在Firefox

生产解决方案

有多种方法可以在应用程序上配置 CORS 策略,并且完全基于您的部署架构。例如,如果您的应用程序将通过反向代理(如 nginx)、API 网关 (Kong)、Service Mesh Sidecar 代理(即 Envoy)、Kubernetes NGINX Ingress 等公开,最佳实践是处理边缘层上的 CORS 配置,因为有时他们不会考虑较低层的标头,并且会覆盖它们,您仍然会从浏览器收到 CORS 错误。 我在下面列出了用于配置边缘层的有用链接

Kubernetes NGINX 入口控制器 CORS - *** / Official User Manual Kong API 网关 - KongHQ Nginx - Geekflare 阿帕奇-Geekflare HA 代理 - Official Website Istio - Discuss.Istio

但是,如果您要通过 SprintBoot 的内置 Web 服务器部署和公开您的 API,您可以使用接下来的说明。

全局启用 CORS 的说明 - Spring Boot 应用程序

如果您没有任何 WebSecurityConfig 实现,只需轻松执行以下步骤:

    添加以下依赖项 [spring-boot-starter-security] 到你的 pom.xml
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
</dependency>
    在您的配置包中创建一个新类,该类扩展 WebSecurityConfig(即“SecurityConfig”) 将以下代码放入创建的文件中:
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;

import java.util.List;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter



    @Override
    protected void configure(HttpSecurity http) throws Exception 
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
        corsConfiguration.setAllowedOrigins(List.of("*"));
        corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT","OPTIONS","PATCH", "DELETE"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setExposedHeaders(List.of("Authorization"));
        
        // You can customize the following part based on your project, it's only a sample
        http.authorizeRequests().antMatchers("/**").permitAll().anyRequest()
                .authenticated().and().csrf().disable().cors().configurationSource(request -> corsConfiguration);

    

    现在您需要根据需要自定义 CORS 配置:

    setAllowedHeaders-> 您必须指定允许通过前端应用程序将哪些参数发送到后端服务,例如,如果您使用 Bearer/Basic Token Authorization 方法,您需要通过“授权”标头传递您的 JWT-Token。因此,您需要确保 backed 会相应地接受此数据,为此,您必须将“授权”放在 Allowed-Headers 列表中。

    setAllowedMethods-> 不要忘记将“OPTIONS”方法放在飞行前过程的列表中。别担心,read more here!

    setAllowCredentials-> 如果您使用的是 Authorization 标头,请将其设置为 True。

    setExposedHeaders-> 如果是通过 Response Headers 返回数据,则需要在此处指定。例如,某些 API 旨在通过响应标头在成功/身份验证后返回授权令牌。因此,需要相应地暴露相关的标头。

    setAllowedOrigins-> 您必须指定有资格向后端应用程序发送请求的域。例如,如果您的应用程序托管在 https://penguin.com 上并且您的 API 在 https://api.penguin.com 上,您需要允许“https://penguing.com”向您的后端发送请求。此外,您可以传递通配符 (*) 以允许任何域向您的后端发送请求。但建议不要使用“any”,除非您提供公共 API 或部署在非生产环境中。

    对于那些可能认为 CORS 可以避免 API 被其他平台/在其他平台上滥用(即网络钓鱼目的)的人来说,存在一个重要的误解。 不是这样,CORS 策略是基于浏览器的策略,可以通过代理轻松绕过,因此只会使滥用过程更加困难,但不会产生免疫。

    构建/运行您的应用程序,测试您的 API,然后休息(每个人都知道 CORS 令人头疼)

替代解决方案

您可以使用以下链接:

Spring.io | Enabling Cross-Origin Requests for a RESTful Web Service

Bealdung | CORS with Spring

【讨论】:

只有 14 个谢谢。我认为原因是因为谷歌没有显示在第一个。这个答案是我找到的最好的,非常感谢。 这为我节省了几个小时,谢谢!一个对我完全有用的小改动,将这一行 corsConfiguration.setAllowedOrigins 更改为 corsConfiguration.setAllowedOriginPatterns @Soroosh Khodami 在同一个域上是否有严格的方法,但对于端口,例如:www.corscheck.com:8081 www.corscheck.com:8056 端口可能会改变,但域将保持不变同样,我怎么能限制只检查域(域事先不知道,它们可能会根据客户而改变) @Shamitha Silva 我认为 HTTP 请求标头中没有源端口的迹象。所以应该在防火墙中管理。【参考方案3】:
// https://docs.spring.io/spring-boot/docs/2.4.2/reference/htmlsingle/#boot-features-cors
@Configuration
public class MyConfiguration 

    @Bean
    public WebMvcConfigurer corsConfigurer() 
        return new WebMvcConfigurer() 
            @Override
            public void addCorsMappings(final CorsRegistry registry) 
                registry.addMapping("/**").allowedMethods("*").allowedHeaders("*");
            
        ;
    

如果使用 Spring Security,设置附加:

// https://docs.spring.io/spring-security/site/docs/5.4.2/reference/html5/#cors
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(final HttpSecurity http) throws Exception 
        // ...

        // if Spring MVC is on classpath and no CorsConfigurationSource is provided,
        // Spring Security will use CORS configuration provided to Spring MVC
        http.cors(Customizer.withDefaults());
    

【讨论】:

【参考方案4】:
@Bean
    public WebMvcConfigurer corsConfigurer() 
        return new WebMvcConfigurer() 
            @Override
            public void addCorsMappings(CorsRegistry registry) 
                registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
            
        ;
    

【讨论】:

不要只是添加答案,试着解释你的答案。 WebMvsConfigure 是一个 bean 创建的。 addMapping("") 表示任何端点,addOrigins("") 表示任何主体都可以访问,allowedMathods("*") 可以提供任何类型的请求 感谢您的解释;)谢谢,这就是我想要的。【参考方案5】:

你可以只用一个单个类来完成这个,只需将它添加到你的类路径中。

对于Spring BootSpring Security,这个一个就足够了,仅此而已。 :

        @Component
        @Order(Ordered.HIGHEST_PRECEDENCE)
        public class MyCorsFilterConfig implements Filter 

            @Override
            public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
                final HttpServletResponse response = (HttpServletResponse) res;
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
                response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, enctype");
                response.setHeader("Access-Control-Max-Age", "3600");
                if (HttpMethod.OPTIONS.name().equalsIgnoreCase(((HttpServletRequest) req).getMethod())) 
                    response.setStatus(HttpServletResponse.SC_OK);
                 else 
                    chain.doFilter(req, res);
                
            

            @Override
            public void destroy() 
            

            @Override
            public void init(FilterConfig config) throws ServletException 
            


        

【讨论】:

【参考方案6】:

Webflux (Reactive) Spring Boot 的解决方案,因为在使用“Reactive”搜索同一问题时,Google 将其显示为最佳结果之一。使用 Spring Boot 2.2.2 版

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) 
  return http.cors().and().build();


@Bean
public CorsWebFilter corsFilter() 
  CorsConfiguration config = new CorsConfiguration();

  config.applyPermitDefaultValues();

  config.addAllowedHeader("Authorization");

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

  return new CorsWebFilter(source);

举个完整的例子,使用自定义身份验证管理器的设置(在我的例子中是 JWT 身份验证)。看这里https://gist.github.com/FiredLight/d973968cbd837048987ab2385ba6b38f

【讨论】:

【参考方案7】:

我通过以下方式解决了这个问题:

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

    @Configuration
    public class CORSFilter extends CorsFilter 

        public CORSFilter(CorsConfigurationSource source) 
            super((CorsConfigurationSource) source);
        

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

            response.addHeader("Access-Control-Allow-Headers",
                    "Access-Control-Allow-Origin, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
            if (response.getHeader("Access-Control-Allow-Origin") == null)
                response.addHeader("Access-Control-Allow-Origin", "*");
            filterChain.doFilter(request, response);
        

    

和:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

    @Configuration
    public class RestConfig 

        @Bean
        public CORSFilter corsFilter() 
            CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration config = new CorsConfiguration();
            config.addAllowedOrigin("http://localhost:4200");
            config.addAllowedMethod(HttpMethod.DELETE);
            config.addAllowedMethod(HttpMethod.GET);
            config.addAllowedMethod(HttpMethod.OPTIONS);
            config.addAllowedMethod(HttpMethod.PUT);
            config.addAllowedMethod(HttpMethod.POST);
            ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**", config);
            return new CORSFilter(source);
        
    

【讨论】:

【参考方案8】:

如果您使用的是 Spring Security,您可以执行以下操作以确保首先处理 CORS 请求:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
    

    @Bean
    CorsConfigurationSource corsConfigurationSource() 
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

更多信息请参见Spring 4.2.x CORS。

如果没有 Spring Security,这将起作用:

@Bean
public WebMvcConfigurer corsConfigurer() 
    return new WebMvcConfigurer() 
        @Override
        public void addCorsMappings(CorsRegistry registry) 
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("GET", "PUT", "POST", "PATCH", "DELETE", "OPTIONS");
        
    ;

【讨论】:

我在我的 MainApplicationFile 中复制了名为“Without Spring Security”的代码解决方案,但它不起作用:( 这些都不适合我。我不断收到带有选项请求的 401。 完美运行!重要的是要记住(如您所说)如果您使用的是 Spring Security,您应该使用第一个代码 sn-p 以确保首先处理 CORS 请求......这就是我的案例的关键。非常感谢!【参考方案9】:

在大量搜索来自 javascript CORS 的错误之后,我为这种情况找到的唯一优雅的解决方案是配置 Spring 自己的类 org.springframework.web.cors.CorsConfiguration.CorsConfiguration() 的 cors

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
    

【讨论】:

【参考方案10】:

Kotlin 解决方案

...
http.cors().configurationSource 
  CorsConfiguration().applyPermitDefaultValues()

...

【讨论】:

【参考方案11】:

我在 Axios、Spring Boot 和 Spring Security 的身份验证方面遇到了重大问题。

请注意您使用的 Spring Boot 版本和 Spring Security。

春季启动:1.5.10 春天:4.3.14 Spring Security 4.2.4

为了使用基于注释的 Java 配置解决此问题,我创建了以下类:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 

        auth.inMemoryAuthentication()
                .withUser("youruser").password("yourpassword")
                .authorities("ROLE_USER");
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 

        http.cors().and().
                authorizeRequests()
                .requestMatchers(CorsUtils:: isPreFlightRequest).permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic()
                .realmName("Biometrix");

        http.csrf().disable();

    

    @Bean
    CorsConfigurationSource corsConfigurationSource() 
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("Authorization"));
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

Axios 的主要问题之一是,当您的 API 需要身份验证时,它会发送带有 OPTIONS 请求的 Authorization 标头。如果你没有在允许的 headers 配置设置中包含 Authorization,我们的 OPTIONS 请求(又名 PreFlight 请求)将会失败并且 Axios 会报错。

您可以通过几个简单且正确放置的设置看到,使用 SpringBoot 配置 CORS 非常简单。

【讨论】:

我一直在寻找这个解决方案。这个对我有用,谢谢。【参考方案12】:

Spring Security 现在可以利用我写的 this blog post 中描述的 Spring MVC CORS 支持。

要使其工作,您需要在 Spring Security 级别显式启用 CORS 支持,如下所示,否则启用 CORS 的请求可能会在到达 Spring MVC 之前被 Spring Security 阻止。

如果您使用控制器级别的@CrossOrigin 注释,您只需启用 Spring Security CORS 支持,它将利用 Spring MVC 配置:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

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

如果您更喜欢使用 CORS 全局配置,您可以声明一个 CorsConfigurationSource bean,如下所示:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

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

    @Bean
    CorsConfigurationSource corsConfigurationSource() 
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    

这种方法取代了之前推荐的filter-based approach。

您可以在 Spring Security 文档的dedicated CORS section 中找到更多详细信息。

【讨论】:

我使用 CorsFilter bean 使 CORS+Spring Security 工作。由于某种原因,FilterRegistrationBean 没有被拾取。 嗨,我有这个: 在我的 dispatcher-servlet 中。这: 在我的 security.xml 中。但是当我打开身份验证时它不起作用。没有日志记录。有什么线索吗? 补充一点,如果你使用@RepositoryRestResource,你必须专门启用它,另一种方式:***.com/questions/31724994/… 嗨,我正在尝试第二种方式,但是 Springs 将每个 JWT 令牌解码为“anonymousUser”。【参考方案13】:

Cors 可能会让人头疼,但有了这个简单的代码,你只是 Cors !!!到指定的方法

@CrossOrigin(origins="*")// in this line add your url and thats is all for spring boot side
    @GetMapping("/some")
    public String index() 
        return "pawned cors!!!!";
    

就像 spring boot 2.0.2 中的魅力

【讨论】:

【参考方案14】:

我通过以下方式解决了这个问题: `

@Bean
CorsConfigurationSource corsConfigurationSource() 
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("*"));
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers","Access-Control-Allow-Origin","Access-Control-Request-Method", "Access-Control-Request-Headers","Origin","Cache-Control", "Content-Type", "Authorization"));
    configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;

`

【讨论】:

【参考方案15】:

我在返回服务器状态的方法上遇到了同样的问题。 该应用程序部署在多台服务器上。所以我发现最简单的就是添加

@CrossOrigin(origins = "*")
@RequestMapping(value="/schedulerActive")
public String isSchedulerActive()
  //code goes here

此方法不安全,但您可以为此添加allowCredentials

【讨论】:

【参考方案16】:

如果你使用 JDK 8+,有一个单行 lambda 解决方案:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());

【讨论】:

它到底是做什么的? javascript 客户端请求将不再抱怨“被 CORS 策略阻止”? 解决了我在使用 Axios 进行 POST 请求时遇到相同 CORS 异常的问题。【参考方案17】:

为 Spring-Boot、Spring-Security 和基于 Java 的配置找到了一个简单的解决方案:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception 
        httpSecurity.cors().configurationSource(new CorsConfigurationSource() 
            @Override
            public CorsConfiguration getCorsConfiguration(HttpServletRequest request) 
                return new CorsConfiguration().applyPermitDefaultValues();
            
        );
    

【讨论】:

你不需要@Configuration,如果你使用@EnableWebSecurity 这适用于我的情况【参考方案18】:

用于属性配置

# ENDPOINTS CORS CONFIGURATION (EndpointCorsProperties)
endpoints.cors.allow-credentials= # Set whether credentials are supported. When not set, credentials are not supported.
endpoints.cors.allowed-headers= # Comma-separated list of headers to allow in a request. '*' allows all headers.
endpoints.cors.allowed-methods=GET # Comma-separated list of methods to allow. '*' allows all methods.
endpoints.cors.allowed-origins= # Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled.
endpoints.cors.exposed-headers= # Comma-separated list of headers to include in a response.
endpoints.cors.max-age=1800 # How long, in seconds, the response from a pre-flight request can be cached by clients.

【讨论】:

这些属性仅适用于 Spring Actuator,并不适用于所有端点。【参考方案19】:

跨源保护是浏览器的一项功能。正如您所假设的,Curl 不关心 CORS。 这就解释了为什么您的 curl 成功,而浏览器请求却没有。

如果您使用错误的凭据发送浏览器请求,spring 将尝试将客户端转发到登录页面。 此响应(在登录页面外)不包含标题“Access-Control-Allow-Origin”,浏览器会按照您的描述做出反应。

您必须使 spring 包含此登录响应的 haeder,并且可能用于其他响应,例如错误页面等。

这可以这样完成:

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter 

            @Override
            public void addCorsMappings(CorsRegistry registry) 
                registry.addMapping("/api/**")
                    .allowedOrigins("http://domain2.com")
                    .allowedMethods("PUT", "DELETE")
                    .allowedHeaders("header1", "header2", "header3")
                    .exposedHeaders("header1", "header2")
                    .allowCredentials(false).maxAge(3600);
            
     

这是从cors-support-in-spring-framework复制的

我将首先为所有资源添加 cors 映射:

registry.addMapping("/**")

并且还允许所有方法标头.. 一旦它起作用,您可能会开始再次将其减少到所需的最低限度。

请注意,CORS 配置随版本 4.2 发生变化。

如果这不能解决您的问题,请发布您从失败的 ajax 请求中获得的响应。

【讨论】:

以上是关于如何在 Spring Boot + Spring Security 应用程序中配置 CORS?的主要内容,如果未能解决你的问题,请参考以下文章

spring boot学习02如何在spring boot项目中访问jsp

Spring 如何在 Spring Boot 中设置数据源

Spring Boot . 3 -- Spring Boot Auto_configuration 是如何实现的?

如何使用 Spring-Boot 播种 Spring-Security

如何在weblogic上运行spring boot

如何在 spring-boot 中配置 Jetty(很容易?)