我使用Spring Boot和Spring Security以及Cors支持 .
如果我执行以下代码
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 季安全中错误认证的标准代码)我得到了
0
以下浏览器通知:
GET http://localhost:5000/api/token
XMLHttpRequest无法加载http://localhost:5000 . 请求的资源上没有'Access-Control-Allow-Origin'标头 . 因此不允许原点'http://localhost:3000'访问 . 响应具有HTTP状态代码401 .
我正在开发前端代码,需要服务器响应中有用的http状态代码来处理这种情况 . 我需要比0更有用的东西 . 响应体也是空的 . 我不知道我的配置是否错误,或者它是一个软件错误,我也不知道在哪里,如果它是铬(使用arch linux)或spring security .
我的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 . 博客文章写道:
即将推出的Spring Boot 1.3版本将提供CORS支持,并且已在1.3.0.BUILD-SNAPSHOT版本中提供 . 在Spring Boot应用程序中使用带有@CrossOrigin注释的控制器方法CORS配置不需要任何特定配置 . 可以通过使用自定义的addCorsMappings(CorsRegistry)方法注册WebMvcConfigurer bean来定义全局CORS配置:
我添加了以下代码以启用全球角色支持 . 实际上我之前尝试过这个但结果是一样的 . 我最近再次尝试过,结果是一样的 .
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}
问题是,问题来自授权过程之间的重定向是一个有趣的问题 . 如何将重定向更改为任何资源以避免此冲突?
编辑:
我想我更接近解决方案 . 我已经使用我的nodejs服务器测试,通过向所有请求添加Access-Control-Allow-Origin:*来支持cors而没有问题 .
就像Stefan Isele已经提到的那样,Spring安全性似乎重定向或者没有添加CORS头部,这就是为什么请求似乎被破坏了 . 因此,虽然Spring安全性正在检查身份验证,但它必须添加正确的标头 .
有谁知道怎么做?
编辑:
我找到了一个解决方法,这看起来很难看 . 我已经为spring boot启动了一个github问题,我在其中描述了解决方法:https://github.com/spring-projects/spring-boot/issues/5834
10 回答
为Spring-Boot,Spring-Security和基于Java的配置找到了一个简单的解决方案:
Spring Security现在可以利用_9925326中描述的Spring MVC CORS支持 .
为了使其工作,您需要在Spring Security级别显式启用CORS支持,如下所示,否则在到达Spring MVC之前,Spring Security可能会阻止启用CORS的请求 .
如果您使用的是控制器级
@CrossOrigin
注释,则只需启用Spring Security CORS支持,它将利用Spring MVC配置:如果您更喜欢使用CORS全局配置,则可以声明
CorsConfigurationSource
bean如下:这种方法取代了以前推荐的filter-based approach .
您可以在Spring Security文档的dedicated CORS section中找到更多详细信息 .
如果您使用的是Spring Security,则可以执行以下操作以确保首先处理CORS请求:
有关更多信息,请参见Spring 4.2.x CORS .
如果您使用JDK 8,则有一行lambda解决方案:
跨源保护是浏览器的一项功能 . 正如你所假设的那样,Curl并不关心CORS . 这就解释了为什么你的卷发成功,而浏览器请求则没有 .
如果您使用错误的凭据发送浏览器请求,spring将尝试将客户端转发到登录页面 . 此响应(在登录页面之外)不包含 Headers “Access-Control-Allow-Origin”,浏览器会按您的描述做出反应 .
您必须使spring包含此登录响应的haeder,并且可能用于其他响应,例如错误页面等 .
这可以这样做:
这是从cors-support-in-spring-framework复制的
我首先要为所有资源添加cors映射:
并且还允许所有方法 Headers ..一旦它工作,你可以开始再次减少到所需的最小值 .
请注意,CORS配置随版本4.2而变化 .
如果这不能解决您的问题,请发布您从失败的ajax请求中获得的响应 .
对于属性配置
我解决了这个问题:`
`
Cors可能是一个痛苦的屁股,但有了这个简单的代码,你只是Cors !!!!到指定的方法
就像 spring 靴2.0.2的魅力
我解决了这个问题问题:
和:
我在返回服务器状态的物品上遇到了同样的问题 . 该应用程序部署在多个服务器上 . 所以我发现最简单的就是添加
此方法不安全,但您可以为此添加
allowCredentials
.