指一个域下的文档或脚本试图去请求另一个域下的资源,由于浏览器同源策略限制而产生
同源策略: 协议+域名+端口三者相同且必须相同
(1). JSONP实现跨域
```
function handleResponse(response) {
console.log(response.data);
}
var script = document.createElement("script");
script.src = "http://example.com/jsonp/getSomething?uid=123&callback=hadleResponse"
document.body.insertBefore(script, document.body.firstChild);
/*handleResponse({"data": "hey"})*/
```
动态添加`script`的标签,可控的去请求远端js并执行,这种跨域方式只能进行GET请求
当我们通过新建一个script标签请求时,后台会根据相应的参数来生成相应的JSON数据。比如说上面这个链接,传递了handleResponse给后台,然后后台根据这个参数再结合数据生成了handleResponse({“data”: “hey”})。
紧接着,这个返回的JSON数据其实就可以被当成一个js脚本,就是对一个函数的调用。
由于我们事先已经声明了这么一个回调函数,于是当资源加载进来的时候,直接就对函数进行调用,于是数据当然就能获取到了。
(2). CORS跨域
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个`Origin`字段。`Origin`字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
如果`Origin`指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含`Access-Control-Allow-Origin`字段,就知道出错了,从而抛出一个错误,被`XMLHttpRequest`的`onerror`回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。
a. Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时`Origin`字段的值,要么是一个`*`,表示接受任意域名的请求。
b. Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为`true`,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为`true`,如果服务器不要浏览器发送Cookie,删除该字段即可。另一方面,开发者必须在AJAX请求中打开`withCredentials`属性
c. Access-Control-Expose-Headers
该字段可选。CORS请求时,`XMLHttpRequest`对象的`getResponseHeader()`方法只能拿到6个基本字段:`Cache-Control`、`Content-Language`、`Content-Type`、`Expires`、`Last-Modified`、`Pragma`。如果想拿到其他字段,就必须在`Access-Control-Expose-Headers`里面指定。上面的例子指定,`getResponseHeader('FooBar')`可以返回`FooBar`字段的值。
总的来说,CORS实现跨域的方法就是根据请求头的Origin值和响应头的Access-Control-Request-Headers和Access-Control-Request-Method的值进行比对,通过了就可以请求成功,没通过就请求失败。
(3). Nginx反向代理接口跨域
实现思路:通过Nginx配置一个代理服务器(域名与example1相同,端口不同)做跳板机,反向代理访问example2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。