跨域方式
2019-07-02 本文已影响0人
糕糕AA
同源策略:不同源的是不能进行请求等操作的,只要满足 协议、主机、端口 一致,则两个页面具有相同的源
跨域:跨域是不可能靠前端单方面解决,总是需要服务器的支持
跨域情况:1、同一父域的子域之间;2、不同父域之间;3、端口不同;4、协议不同
- 3、4需要通过Proxy:发起方的域下创建Proxy程序,发起方的域下调用Proxy,Proxy将请求发送给接收方并获取相应数据,Proxy将获得数据返回给发起的js
1、document.domain+iframe
(只能解决1):在发起和接收方设置document.domain,并设置为父域的主域名(window.location.hostname);发起方页面创建隐藏的iframe,iframe的源是接收方页面;根据浏览器的不同,通过iframe.contentDocument || iframe.contentWindow.document来获得接收方页面的内容;通过接收方页面的内容与接收方进行交互。(缺点:当一个域被攻击,另一个域有安全漏洞出现)
2、jsonp
- HTML标签中src和href属性可以请求外部地址,没有跨域限制,根据src这一特性,得到jsonp的跨域请求方式
- 通过动态添加<script>的标签,可控的去请求远端js并执行
- 与服务器约定好一个回调函数,服务器收到请求返回一段js,这段js中调用约定好的回调函数,并将数据作为作为参数传递。网页收到这段js代码,执行回调,数据成功返回。
- jsonp缺点:只支持get方式,脚本注入行为存在安全隐患。
(1)代码实现:
var script = document.createElement('script'); // 创建script标签
script.type = 'text/javascript'; // 设置type
// 传参并指定回调执行函数为onBack
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack'; // 设置src,要访问的地址。提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
document.head.appendChild(script); // 将标签插入文档头部
// 回调函数
function onBack(res) { // 设置回调函数,获取返回的数据,并处理
alert(JSON.stringify(res));
}
//服务端返回如下(返回时即执行全局函数):
onBack({"status": true, "user": "admin"})
(2)jquery ajax:
$.ajax({
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "onBack", // 自定义回调函数名
data: {}
});
3、Proxy解决跨域问题:
- 开发 webpack proxy-middleware代理
- proxy 的工作机制是:你依然请求本地地址,即使你 npm run dev 跑起来的东西并没有任何接口能力,而 Webpack 后台会将所有指定的请求转发到 target 对应的地址上。这个转发的过程发生在服务端(也就是 webpack-dev-server),所以浏览器是不知道的。
proxy: {
'/api': {
target: 'https://list.jd.com/list.html?cat=1318,1462,1480&callback=jQuery942326&md=9&l=jdlist&go=0',
pathRewrite: {'^/api' : ''},
changeOrigin:true, //必须要加,否则是访问自己
}
}
- 生产 nginx代理
* 生产环境 配置nginx.conf
js
location /api {
# 这里也可以录用原有参数,进行复用,并重写URL
proxy_pass https://list.jd.com/list.html?cat=1318,1462,1480&callback=jQuery942326&md=9&l=jdlist&go=0;
}
4、 cors:需要与服务端配合
- “跨域资源共享”,允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
- 同源策略不仅在浏览器有限制,在服务端也有限制
- 简单请求:方法为HEAD、GET或者POST中的一种;HTTP的头信息不超过以下几种字段Accept、Accept-Language、Content-Language、Last-Event-ID以及Content-Type的值只限于application/x-www-form-urlencoded、multipart/form-data、text/plain三个
简单请求时,浏览器会自动在请求头中添加一个字段Origin,值为发出请求网页的源地址。服务端根据这个值,决定是否同意这次请求,如果Origin的值不在指定的许可范围,服务端返回一个正常的HTTP回应。浏览器未找到Access-Control-Allow-Origin字段,则抛出错误,但这个错误无法通过状态吗识别 - 非简单请求:PUT或DELETE,或者Content-Type字段的类型是application/json。浏览器会在正式请求之前发送一次预检请求,option`请求。正式请求之前,浏览器会去问服务端我这个地址能不能访问你,如果可以,浏览器才会发送正式的请求,否则报错。
- 总的来说:CORS实现跨域的方法就是根据请求头的Origin值和响应头的Access-Control-Request-Headers和Access-Control-Request-Method的值进行比对,通过了就可以请求成功,没通过就请求失败。
JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
反向代理:node,Nginx
同源策略只是浏览器的一个安全策略,只适用于浏览器向服务器发送请求的时候,当服务器跟服务器发送请求的时候,自然就没有这么一层限制,只要是接口,就会返回。
权限不通过的时候,也是会请求成功200的,只是返回的是“需要登录”等信息
- 正向代理:客户端知道谁是真正返回数据的服务器
- 反向代理:客户端不知道谁是返回数据的服务器