同源策略
- 跨域为了解决浏览器同源策略的限制
- 域名相同,端口相同,协议相同即为同源
- 不同源的Cookie、LocalStorage 和 IndexDB 无法读取
- 不同源的Dom无法获取
- 不同源的AJAX异步请求不能发送
CORS(Cross-origin resource sharing)跨域资源请求
浏览器在请求资源时,如果是跨域ajax请求,会在请求头添加origin字段
服务器接收到请求返回资源给浏览器,会在请求头添加Access-Control-Allow-Origin字段
如果当前域没有在该字段当中标识,则浏览器会把返回内容忽略掉,并且在控制台报错
限制
允许的请求方法
- GET
- POST
- HEAD
允许的 Content-Type
- text/plain
- multipart/form-data
- application/x-www-form-ulencoded
其他的请求方法和 Content-Type类型需要通过预请求验证后才能发送
预请求
规范要求,对服务器数据产生副作用的 HTTP 请求方法(GET 以外的 HTTP 请求,不是幂等的请求),浏览器必须首先使用 OPTIONS 发起一个预检请求
服务器在 HTTP header 中加入允许请求的方法和 Content-Type 后,之后浏览器异步请求指定的方法和 Content-Type 就可以跨域请求了
Access-Control-Allow-Headers: 允许Content-TypeAccess-Control-Allow-Methods: 允许的请求方法Access-Control-Max-Age: 预请求允许其他方法和类型传输的时间
JSONP 跨域
浏览器上虽然有同源限制,但是像 srcipt 标签、link 标签、img 标签、iframe 标签可以跨域
通过 src 地址来加载内容时,浏览器允许跨域请求
原理
创建一个 script 标签,这个 script 标签的 src 就是请求的地址
这个 script 标签插入到 DOM 中,浏览器就根据 src 地址访问服务器资源
返回的资源是一个文本,但是因为是在 script 标签中,浏览器会执行它
而这个文本恰好是函数调用的形式,即函数名(数据),浏览器会调用这个函数
只要提前约定好这个函数名,并且这个函数存在于 window 对象中,就可以把数据传递给处理函数
Hash 跨域通信
在页面 A 下提供 iframe 或 frame 嵌入跨域页面 B
在 A 页面中改变 B 的 url 中的 hash 值,B 不会刷新,但是 B 可以用过 window.onhashchange 事件监听到 hash 变化
postMessage 通信
窗口A中window.postMessage("data", "http://A.com")窗口B中window.addEventListener("message", function(event) {console.log(event.origin) http://A.comconsole.log(event.source) A 对象window引用console.log(event.data) 数据})
WebSoket 跨域通信
var ws = new WebSocket("wss://echo.websoket.org") //这个是后端端口ws.onopen = function(evt) {ws.send("some message")}ws.onmessage = function(evt) {console.log(evt.data)}ws.onclose = function(evt) {console.log("连接关闭")}
document.domain
该方式只用于二级域名相同的情况下
只需要给页面添加 document.domain = 'test.com' 表示 二级域名相同就可以实现跨域
