跨域
目录
跨域!!
什么情况造成跨域?
同源策略限制 不同源会造成跨域。以下任意一种情况不同,都是不同源。
http://
协议不同- www子域名不同
- baidu.com主域名不同
- 8080端口号不同
- www.baidu.comip地址和网址不同
跨域解决方案
jsonp , cors , Nginx等
jsonp
只能解决 GET 跨域
- 原理:同源策略不能请求不同域的数据,但是可以引入不同域的js脚本。因为所有的src属性和href属性都不受同源策略限制。可以载入js脚本,然后触发回调函数,将json数据作为参数传入函数进行处理。
- 步骤:
- 创建script标签
- script的src属性设置接口地址
- 接口参数,必须要带一个回调函数 要不然后台无法返回数据。
- 通过回调函数去接收后台返回数据
//去创建一个script标签
var script = document.createElement("script");
//script的src属性设置接口地址 并带一个callback回调函数名称
script.src = "http://127.0.0.1:8888/index.php?callback=jsonpCallback";
//插入到页面
document.head.appendChild(script);
//通过定义函数名去接收后台返回数据
function jsonpCallback(data){
//注意 jsonp返回的数据是json对象可以直接使用
//ajax 取得数据是json字符串需要转换成json对象才可以使用。
}
封装一个jsonp函数:
function jsonp({ url, params, callback }) {
return new Promise((resolve, reject) => { //返回一个promise对象
let script = document.createElement('script') //新建一个script
window[callback] = function(data) {
resolve(data)
document.body.removeChild(script)
}
params = { ...params, callback } // wd=b&callback=show
let arrs = []
for (let key in params) {
arrs.push(`${key}=${params[key]}`)
}
script.src = `${url}?${arrs.join('&')}`
document.body.appendChild(script)
})
}
jsonp({
url: ' ',
params: { },
callback: '
}).then(data => {
//其他处理
})
- jquery 的jsonp形式
$.ajax({
url:"http://crossdomain.com/jsonServerResponse",
dataType:"jsonp",
type:"get",//可以省略
jsonpCallback:"show",//->自定义传递给服务器的函数名,而不是使用jQuery自动生成的,可省略
jsonp:"callback",//->把传递函数名的那个形参callback,可省略
success:function (data){
console.log(data);
}
});
CORS:跨域资源共享
支持 XmlHttpRequest 的跨域请求。
- 原理:服务器设置 Access-Control-Allow-Origin 的HTTP响应头之后,浏览器将会允许跨域请求
- 限制:浏览器需要支持HTML5,可以支持POST,PUT等方法兼容ie9以上
需要后台设置
Access-Control-Allow-Origin: * //允许所有域名访问,或者
Access-Control-Allow-Origin: http://a.com //只允许所有域名访问
-
简单请求
满足条件:- 使用 GET/HEAD/POST
- Content-Type值为:text/plainmulti,或part/form-data,application/x-www-form-urlencoded
-
非简单请求
在正式请求之前有"预检", 用option方法检查服务器是否支持cors
postMessage()
跨窗口, 页面与iframe,页面与新窗口之间传递数据。
otherWindow.postMessage(message, targetOrigin, [transfer]);
- message:数据
- targetOrigin:URI,origin 属性指定哪些窗口可以收到消息
webSocket
HTML5的一个持久化协议,全双工通信,Client 和 Server 都可以主动收发数据。
建立连接时借助HTTP协议,建立后与HTTP无关。
socket.io 封装了 webSocket API。
Node中间件代理
代理服务器转发请求和响应,不受同源限制。
Nginx反向代理
- 搭建一个中转nginx服务器,用于转发请求
只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能
实现:
通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
window.name + iframe
通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域
location.hash + iframe
页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信
document.domain + iframe
要求二级域名相同