我使用带有Spring Security 和cors支持的spring引导。
如果我执行以下代码
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(这是springsecurity中错误身份验证的标准代码),而是得到了
0
具有以下浏览器通知:
得到http://localhost:5000/api/令牌
无法加载xmlhttprequesthttp://localhost:5000. 请求的资源上不存在“access control allow origin”标头。'原点'http://localhost:3000'因此不允许访问。响应具有http状态代码401。
我正在开发前端代码,需要从服务器响应中获得有用的http状态代码来处理这种情况。我需要比0更有用的东西。响应主体也是空的。我不知道我的配置是不是错了,或者是一个软件错误,我也不知道在哪里,是chromium(使用archlinux)还是spring安全。
我的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.3Spring Boot。博客写道:
cors支持将在即将发布的springboot1.3版本中提供,并且已经在1.3.0.build-snapshot版本中提供。
在spring引导应用程序中使用带有@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("/**");
}
};
}
}
不过,这个问题来自授权过程之间的重定向的想法很有趣。如何将重定向更改为任何资源以避免此冲突?
编辑:
我想我离解决问题更近了。我已经用我的nodejs服务器进行了测试,该服务器通过向所有请求添加访问控制allow origin:*来支持cors,没有任何问题。
就像stefanisele已经提到的那样,Spring Security 似乎重定向或没有添加cors头,所以请求似乎被破坏了。因此,当Spring Security 检查身份验证时,它必须添加适当的头。
有人知道怎么做吗?
编辑:
我找到了一个解决办法,看起来很难看。我已经开始为spring boot发布github,在这里我描述了解决方法:https://github.com/spring-projects/spring-boot/issues/5834
13条答案
按热度按时间qcbq4gxm1#
springsecurity现在可以利用springmvccors支持,这在我写的这篇博文中有描述。
要使其工作,您需要在spring安全级别显式启用cors支持,如下所示,否则在到达spring mvc之前,启用cors的请求可能会被Spring Security 阻止。
如果您使用的是控制器级别
@CrossOrigin
注解,您只需启用spring security cors支持,它将利用spring mvc配置:如果您喜欢使用cors全局配置,可以声明
CorsConfigurationSource
如下所示:这种方法取代了以前推荐的基于过滤器的方法。
您可以在spring安全文档的cors部分找到更多细节。
dfddblmv2#
如果使用jdk 8+,则有一个单行lambda解决方案:
szqfcxe23#
如果您使用的是spring security,则可以执行以下操作以确保首先处理cors请求:
有关更多信息,请参见Spring4.2.xCORS。
如果没有spring security,这将起作用:
v6ylcynt4#
跨源保护是浏览器的一项功能。curl不喜欢cors,就像你想象的那样。这就解释了为什么你的卷发是成功的,而浏览器的请求不是。
如果使用错误的凭据发送浏览器请求,spring将尝试将客户端转发到登录页。此响应(不在登录页上)不包含标题“访问控制允许源站”,浏览器的响应如您所述。
您必须使spring包含此登录响应的haeder,并且可能包含其他响应,如错误页等。
可以这样做:
这是从spring框架中的cors支持复制的
首先,我将为所有资源添加corsMap:
还允许所有方法的头。。一旦它起作用,你可以开始再次减少到所需的最低限度。
请注意,cors配置随4.2版而变化。
如果这不能解决您的问题,那么发布失败的ajax请求的响应。
t5zmwmid5#
我通过以下方法解决了这个问题:
以及:
insrf1ej6#
suzh9iv87#
为spring boot、spring security和基于java的配置找到了一个简单的解决方案:
wz1wpwve8#
如何解决springboot2.3上的cors问题+
摘要
如果你面对的是cors问题,别担心。当每个后端开发人员第一次尝试与前端微服务集成时,这是一个常见的问题。这是某种安全策略,浏览器严格地应用于用户的安全,这就是为什么当你通过postman/swagger或curl尝试api时,你不会面对它。
解决方案
客户端旁路(仅适用于开发人员)
以下解决方案仅用于开发目的,您绝对需要为您的生产环境永久性地解决这个cors问题。您可以使用以下浏览器扩展绕过cors错误的浏览器策略,但如果这些策略不能正常工作,请不要感到惊讶。
cors取消阻止firefox-chrome
无处不在的cors firefox
生产解决方案
在应用程序上配置cors策略有不同的方法,完全基于您的部署体系结构。例如,如果您的应用程序将通过反向代理(如nginx)、api网关(kong)、service mesh sidecar代理(即特使)、kubernetes nginx入口等公开,最好的做法是处理边缘层上的cors配置,因为有时它们不考虑较低层的头,它们会覆盖它们,并且您仍然会从浏览器接收cors错误。我在下面列出了边缘层配置的有用链接
kubernetes nginx入口控制器cors-stackoverflow/官方用户手册
kong api网关-konghq
nginx-geekflare公司
Apache-geekflare
ha代理-官方网站
istio-讨论.istio
但是,如果您打算通过sprintboot的内置web服务器部署和公开api,那么您可以使用下面的说明。
全局启用cors的说明—spring引导应用程序
如果没有WebSecurity配置的任何实现,只需简单地执行以下步骤:
将以下依赖项[spring boot starter security]添加到pom.xml中
在您的配置包中创建一个新类,扩展websecurityconfig(即“securityconfig”)
将以下代码放入创建的文件中:
现在您需要根据需要自定义cors配置:
setallowedheaders->您必须指定哪些参数允许通过前端应用程序发送到后端服务,例如,如果您使用的是承载/基本令牌授权方法,则需要通过“authorization”头传递jwt令牌。因此,您需要确保backed会相应地接受这些数据,为此,您必须在允许的头列表中添加“authorization”。
setallowedmethods->不要忘记将“选项”方法放在飞行前处理的列表中。别担心,在这里读更多!
setallowcredentials->如果使用的是授权标头,请将其设置为true。
setexposedheaders->如果通过响应头返回数据,则需要在此处指定它们。例如,一些api被设计成在成功/认证后通过响应头返回授权令牌。因此,需要相应地公开相关的报头。
setallowedorigins->必须指定有资格向后端应用程序发送请求的域。例如,如果您的应用程序托管在https://penguin.com and 你的API打开了https://api.penguin.com,您需要允许“https://penguing.com“向后端发送请求。此外,您还可以传递通配符(*),以允许任何域向后端发送请求。但建议不要使用“any”,除非您正在提供公共api或在非生产环境中部署。
有一个重要的误解,人们可能认为cors可以避免误用API的/在其他平台上(即钓鱼目的)。这不是真的,cors策略是基于浏览器的策略,可以通过代理轻松绕过,因此它只会使误用过程变得更加困难,但不会产生免疫力。
构建/运行应用程序、测试api和rest(每个人都知道cors)
替代解决方案
您可以使用以下链接:
spring.io |为restful web服务启用跨源请求
带Spring的bealdung | cors
qmb5sa229#
属性配置
irlmq6kh10#
我通过以下方法解决了这个问题:`
`
hs1ihplo11#
我在返回服务器状态的方法上遇到了同样的问题。应用程序部署在多个服务器上。所以我发现最简单的方法就是
此方法不安全,但您可以添加
allowCredentials
为了这个。xriantvc12#
cors可能是一个痛苦的屁股,但与这个简单的代码,你只是cors!!!!按指定方法
就像春靴2.0.2中的魅力
92dk7w1h13#
我在axios、spring boot和spring身份验证安全性方面遇到了重大问题。
请注意spring boot的版本