如何在 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 Boot、Spring 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 没有被拾取。
嗨,我有这个: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 Boot . 3 -- Spring Boot Auto_configuration 是如何实现的?