1、什么是跨域
在了解跨域之前,首先要知道什么是同源策略(same-origin policy)。简单来讲同源策略就是浏览器为了保证用户信息的安全,防止恶意的网站窃取数据,禁止不同域之间的JS进行交互。对于浏览器而言只要域名、协议、端口其中一个不同就会引发同源策略,从而限制他们之间如下的交互行为:
- Cookie、LocalStorage 和 IndexDB 无法读取。
- DOM 无法获得。
- AJAX 请求能发送,浏览器不接收响应。(这是我们要解决的)
2、解决ajax跨域请求的几种方法
1、服务端使用反向代理,把跨域改为不跨域
2、客户使用jsonp方式发起请求(老浏览器都支持)
3、服务端支持CORS (ie8、ie9不支持,高级浏览器支持) (这是我们采取的解决方案)
3、服务端支持CORS的几种方法
- Spring mvc项目可使用 @CrossOrigin(origins = "*", maxAge = 3600)注解,声明支持跨域。
- Spring mvc项目可使用<mvc:cors/> 在配置支持跨域。文档: 使用<mvc:cors/>来实现CORS跨域的支持 。
- 自已开发过滤器。文档: 使用CorsFilter来实现CORS跨域的支持 (这是我们采取的解决方案)
4. CORS 简介
同源策略(same origin policy)是浏览器安全的基石。在同源策略的限制下,非同源的网站之间不能发送 ajax 请求的。
为了解决这个问题,w3c 提出了跨源资源共享,即 CORS(Cross-Origin Resource Sharing)。
CORS 做到了两点:
- 不破坏即有规则
- 服务器实现了 CORS 接口,就可以跨源通
基于这两点,CORS 将请求分为两类:简单请求和非简单请求。
4.1 简单请求
可以先看下 CORS 出现前的情况:跨源时能够通过 script 或者 image 标签触发 GET 请求或通过表单发送一条 POST 请求,但这两种请求 HTTP 头信息中都不能包含任何自定义字段。
简单请求对应该规则,因此对简单请求的定义为:
请求方法是 HEAD、GET 或 POST 且 HTTP 头信息不超过以下几个字段:
Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type
(只限于 application/x-www-form-urlencoded、multipart/form-data、text/plain)。
对于这样的简单请求,CORS 的策略是请求时,**在头信息中添加一个 Origin 字段**,服务器收到请求后,根据该字段判断是否允许该请求。
如果允许,则在 HTTP 头信息中添加 Access-Control-Allow-Origin 字段,并返回正确的结果
如果不允许,则不在头信息中添加 Access-Control-Allow-Origin 字段。
浏览器先于用户得到返回结果,根据有无 Access-Control-Allow-Origin 字段来决定是否拦截该返回结果。
对于 CORS 出现前的一些服务,CORS 对他们的影响分两种情况:
script 或者 image 触发的 GET 请求不包含 Origin 头,所以不受到 CORS 的限制,依旧可用。
如果是 ajax 请求,HTTP 头信息中会包含 Origin 字段,由于服务器没有做任何配置,所以返回结果不会包含
Access-Control-Allow-Origin,因此返回结果会被浏览器拦截,接口依旧不可以被 ajax 跨源访问。
可以看出,CORS 的出现,没有对”旧的“服务造成任何影响。
另外,除了提到的 Access-Control-Allow-Origin 还有几个字段用于描述 CORS 返回结果:
Access-Control-Allow-Credentials: 可选,用户是否可以发送、处理 cookie。
Access-Control-Expose-Headers:可选,可以让用户拿到的字段。有几个字段无论设置与否都可以拿到的,包括:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。
4.2 非简单请求
除了简单请求之外的请求,就是非简单请求。
对于非简单请求的跨源请求,浏览器会在真实请求发出前,增加一次 OPTION 请求,称为预检请求(preflight request)。预检请求将真实请求的信息,包括请求方法、自定义头字段、源信息添加到 HTTP 头信息字段中,询问服务器是否允许这样的操作。
比如对于 DELETE 请求:
OPTIONS /test HTTP/1.1
Origin:
http://www.examples.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: X-Custom-Header
Host:
www.examples.com
与 CORS 相关的字段有:
Access-Control-Request-Method: 真实请求使用的 HTTP 方法。
Access-Control-Request-Headers: 真实请求中包含的自定义头字段。
服务器收到请求时,需要分别对 Origin、Access-Control-Request-Method、Access-Control-Request-Headers 进行验证,验证通过后,会在返回 Http 头信息中添加
Access-Control-Allow-Origin:
http://www.examples.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
他们的含义分别是:
Access-Control-Allow-Methods: 真实请求允许的方法
Access-Control-Allow-Headers: 服务器允许使用的字段
Access-Control-Allow-Credentials: 是否允许用户发送、处理 cookie
Access-Control-Max-Age: 预检请求的有效期,单位为秒。有效期内,不会重复发送预检请求
当预检请求通过后,浏览器会发送真实请求到服务器。这就实现了跨源请求。
参考:
https://www.cnblogs.com/cc299/p/7339583.html
https://www.cnblogs.com/fanshuyao/p/7168471.html
https://blog.csdn.net/q826qq1878/article/details/81230936
https://www.cnblogs.com/pangguoming/p/7402661.html
http方法
下面说下restful的http方法:GET、HEAD、POST、PUT、DELETE、OPTIONS、TRACE、PATCH
根据RFC2616第九章说明,http方法的定义有两点:safe and Idempotent,即安全性和幂等性,可以结合这两点对以上方法进行说明
1,GET
安全、幂等;
用于获取资源;
2,HEAD
安全、幂等;
与get方法类似,但不返回message body内容,仅仅是获得获取资源的部分信息(content-type、content-length);
restful框架中较少使用
3,POST
非安全、非幂等;
用于创建子资源
4,PUT
非安全、幂等;
用于创建、更新资源;
5,DELETE
非安全、幂等;
删除资源;
6,OPTIONS
安全、幂等;
用于url验证,验证接口服务是否正常;
7,TEACE
安全、幂等;
维基百科“回显服务器收到的请求,这样客户端可以看到(如果有)哪一些改变或者添加已经被中间服务器实现。”
restful框架中较少使用
8,PATCH
非安全、幂等;
用于创建、更新资源,于PUT类似,区别在于PATCH代表部分更新;
后来提出的接口方法,使用时可能去要验证客户端和服务端是否支持;