CORS跨域与@crossorigin

在这之前只是知道两者各自是什么,但却一直不清楚两者的关系,如今总结为下:

CORS,全称是"跨域资源共享"(Cross-origin resource sharing)

它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了Ajax只能同源使用的限制。

基本思想是:使用自定义的HTTP头部允许服务器和浏览器相互了解对方,从而决定请求或响应成功与否。

处理简单请求:

(1) 请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

(2)HTTP的头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

与CORS有关的头部是:

  • Access-Control-Allow-Origin:*,即为接受全部,而为了防止XSS攻击,我们需要把这个头部的值限制为某个域,如:Access-Control-Allow-Origin: http://www.csdn.net;
  • Access-Control-Allow-Credentials:true/false;表示是否允许发送cookie,默认情况下,不会自动带上cookie,这个值为true时为表示服务器明确许可,cookie可以包含在请求中,需配合Ajax中的withCredentials = true来携带cookie发送请求。
  • Access-Control-Expose-Headers:foobar;可选字段。在该字段里指定返回字段,就可以通过XMLHttpRequest对象的getResponseHeader()方法拿到foobar字段的值。(通常只能拿到Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma 这六个基本字段的值)。

使用CORS需要注意:

  • Ajax请求中需要设置withCredentials = true;并且这时Access-Control-Allow-Origin的值不能为*,须为具体域名。
  • Access-Control-Allow-Origin不能配置多个请求服务器,但可以通过静态配置多个的方式,根据referer匹配,匹配到相对应的设置Access-Control-Allow-Origin为这个方式。

处理非简单请求:

不是简单请求则为非简单请求,如请求方法是PUT或者DELETE,或者Content-Type字段的类型是application/json。

非简单请求的CORS请求,会在正式通信之前增加一次HTTP查询请求,称为“预检”请求。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

  • 预检请求用的方法是OPTIONS,表示这个请求是用来询问的。关键字段是Origin,表示请求来自哪个源。
  • 除了Origin之外,还有两个特殊字段:
  • Access-Control-Request-Method:该字段是必须的,用来列出CORS请求会用到那些方法。
  • Access-Control-Request-Headers:该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段。

服务器收到"预检"请求以后,检查了OriginAccess-Control-Request-MethodAccess-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

@crossorigin:Handler阶段的CORS

概念:

@crossorigin是后端SpringMVC框架(需4.2版本以上)Controller层的一个注解这个注解是用在控制器方法上的,其实Spring在这里用的还是CorsInterceptor,做最后一层拦截,这也就解释了为什么CorsInterceptor永远是最后一个执行的拦截器。可处理跨域请求,设置为:

@crossorigin(origins = "*",maxAge = 3600)

例:

// 先把WebConfig中前两阶段的配置(CorsFilter和CorsInterceptor)注释掉,再到这里加跨域注解
@CrossOrigin(origins = "http://localhost:3000")
@RequestMapping(method = RequestMethod.GET)
List<User> getList() {
    return Lists.newArrayList(userdb.asMap().values());
}

另外两个不同阶段:

 

  • CorsFilter: 过滤器阶段的CORS,
  • CorsInterceptor: 拦截器阶段的CORS

以上CORS资料来自阮一峰大神:跨域资源共享CORS详解

@crossorigin资料来自简书:SpringMVC开启CORS支持

猜你喜欢

转载自blog.csdn.net/baibaider/article/details/79793449
今日推荐