在了解跨域这个概念以前首先要知道的是何为同源策略。所谓的同源是一种安全机制,为了预防某些恶意行为(例如 Cookie 窃取等),浏览器限制了从同一个源加载的文档或脚本如何与来自另外一个源的资源进行交互。而知足同源要具有三方面:协议相同、域名相同、端口相同。javascript
如下是对于http://domain.com/dir/index.html
(默认端口 80)来进行同源判断:html
http://domain.com/dir2/info.html
(同源)https://domain.com/dir/index.html
(非同源,协议不相同)http://www.domain.com/dir/index.html
(非同源,域名不一样)http://domain.com:233/dir/index.html
(非同源,端口不一样)同源策略对于用户信息安全是必不可少的,可是实现合理的跨域请求也是很重要的,因而 W3C 就定了一个叫CORS(Cross-Origin Resource Sharing)的草案,也就是跨域资源共享。其基本思想就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功或是失败。java
实现 CORS 须要浏览器与服务器的同时支持。例如发送一个简单的GET
或POST
请求,浏览器会为其添加一个Origin
的头,其包含页面的源信息(协议、域名和端口),如:jquery
Origin: http://domain.com
复制代码
若服务器认为该请求可接受,就在Access-Control-Allow-Origin
头部中回发相同的源信息(咱们有时调用的公共 API,大部分都是将该头部设为*
,可是它们都不发送 Cookie)。要注意的是请求和响应都不包含 Cookie 信息。nginx
以上都为简单请求,对于非简单请求,CORS 经过一种叫作 Preflighted Requests 的透明服务器验证机制支持开发者使用自定义头部信息或者 GET 和 POST 以外的方法,不过代价是在正式通讯前增长一次 HTTP 请求,这里就不详细描述了。ajax
现代浏览器都对 CORS 提供了原生支持(IE八、9 是利用XDomainRequest
,不过已废弃),无需编写额外代码便可触发简单的跨域行为,由于浏览器会自动帮你添加一些头部信息,可是有如下限制:json
setRequestHeader()
设置自定义头部。Access-Control-Allow-Credentials
设为true
。getAllResponseHeaders()
会返回空字符串。该跨域技术主要是利用<img>
标签设置src
属性(请求地址一般都带有查询字符串),而后监听该<img>
的onload
或onerror
事件来判断请求是否成功。响应的内容一般是一张 1 像素的图片或者204
响应。跨域
图片 Ping 有两个缺点:浏览器
<img>
标签实现,因此只支持GET
请求。因为以上特色,图片 Ping 方法经常使用于跟踪用户点击页面或动态广告的曝光次数。安全
JSONP 是 JSON with padding 的简写,其主要是利用动态建立<script>
标签向服务器发送 GET 请求,服务器收到请求后将数据放在一个指定名字的回调函数中并传送回来。接下来看一下简单示例: 浏览器:
//对建立标签行为进行封装
function addScriptTag(src) {
var script = document.createElement('script')
script.setAttribute("type","text/javascript")
script.src = src
document.body.appendChild(script)
}
//当浏览器加载完毕时向服务器发送请求
window.onload = function () {
addScriptTag('http://domain.com/data?callback=getdata')
}
//服务器收到上面的请求后,将数据放在回调函数的参数(data)中返回
function getdata(data) {
console.log(data)
}
复制代码
jQuery 也有对 JSONP 的封装,有兴趣的能够了解一下(文章尾部连接)
服务器
//服务器获取参数名后,将回调函数和参数拼接为字符串返回
response.send(
`${query.callback}({ "name": "Hello" })`
)
复制代码
跨域方法其实还有很多,这里先总结这么多,日后若时间容许的话就更新 😬