文章目录
跨域
1、怎么算跨域
请求地址与当前页面访问地址
中的协议、域名或IP、端口全部一致则称为同源,
若有一个不一致则不同源,也就是跨域。
2、浏览器具体是如何做到的
具体实现方式就是,XMLHttpRequest和Fetch这两个API都部署了同源限制
。
,
Web中的四种跨域的解决方案
1、JSONP
- 原生写法
<script src="http://domain/api?param1=6&callback=jsonp"></script>
<script>
function jsonp(data) {
console.log(data)
}
</script>
- 封装后写法
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://example.com/ip?callback=foo');
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
-
JSONP的具体流程
-
第一步,网页添加一个<script>元素,向服务器请求一个脚本,这不受同源政策限制,可以跨域请求。
<script src="http://api.foo.com?callback=bar"></script>
注意,请求的脚本网址有一个callback参数(?callback=bar),用来告诉服务器,客户端的回调函数名称(bar)。
-
第二步,服务器收到请求后,将返回的JSON 数据,放在函数名里面,最终作为字符串返回,即返回的内容就是---bar({...})
-
第三步,客户端会将服务器返回的字符串,作为代码进行解析
,
因为浏览器认为,这是<script>
标签请求的脚本内容。这时,客户端只要定义了bar()函数,就能在该函数体内,拿到服务器返回的 JSON 数据。
-
-
JSONP跨域的原理
利用 <script> 标签中的src属性,不受浏览器同源策略影响的特性。通过 <script> 标签中的src属性指向一个需要访问的地址,并且我们可以通过传递一个callback函数来接收并处理返回信息 -
JSONP跨域的缺陷
只限于 get 请求
2、websocket通信
WebSocket 是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀
。
该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
3、CORS通信
CORS主要是服务器来实施的,在服务器端,需要在响应头
中设置指定允许访问的IP/域名( Access-Control-Allow-Origin),也就是让服务器告知浏览器,这个域名是否被允许访问我的资源。
浏览器通过读取这些头信息
可以了解到这个跨源资源是不是应该被读取。
CORS包含的响应头信息
常用响应头:
Access-Control-Allow-Origin: <origin> | *
# 允许访问的请求头有哪些
Access-Control-Allow-Methods: <method>[, <method>]*
# 允许访问的请求方式
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
# 允许添加的请求头
Access-Control-Max-Age: <delta-seconds>
# 指定了请求的结果能够被缓存多久
Access-Control-Allow-Credentials: true
# Credentials 证书,在ajax中指cookie, 这个设置为true代表发送cookie(跨域的情况)
CORS包含的请求头信息
常用请求头
Origin: <origin>
# 请求地址的origin
Refer:<refer>
# 请求地址
Access-Control-Request-Method: <method>
# 只出现在预检请求中
Access-Control-Request-Headers: <field-name>[, <field-name>]*
# 只出现在预检请求中
4、服务器代理
跨域限制是被浏览器限制的,因此如果用服务器作为代理来请求跨域资源,就不会有这个限制了。
即浏览器端发送同源请求,服务端去发送真正的跨域请求,服务端获取返回后,再将结果返回给浏览器。
5、document.domain
利用document.domain 实现跨域的前提条件:
这种方法,只适用于同一个域名下的不同的二级域名之间,使用document.domain = '主域名' 来实现跨域)
6、iframe可通过postMessage实现跨域通信
这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息
- 在A页面中,获取B页面的window对象,通过postMessage方法发送数据。
otherWindow.postMessage(message, targetOrigin, [transfer]);
- 在B页面中,通过监听message事件来接收传递过来的数据。
window.addEventListener("message", function(event) {
console.log(event, event.data);
}, false);
案例如下:
父窗体创建跨域iframe并发送信息
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>跨域POST消息发送</title>
</head>
<body>
<textarea id="message"></textarea>
<input type="button" value="发送" onclick="sendPost()">
<iframe src="http://moweide.gitcafe.io/other-domain.html" id="otherPage" style="display:none"></iframe>
</body>
<script type="text/JavaScript">
// sendPost 通过postMessage实现跨域通信将表单信息发送到 moweide.gitcafe.io上, 并取得返回的数据
function sendPost() {
// 获取id为otherPage的iframe窗口对象
var iframeWin = document.getElementById("otherPage").contentWindow;
// 向该窗口发送消息
iframeWin.postMessage(document.getElementById("message").value,http://moweide.gitcafe.io');
}
// 监听跨域请求的返回
window.addEventListener("message", function(event) {
console.log(event, event.data);
}, false);
</script>
</html>
子窗体接收信息并处理
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>POST Handler</title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/JavaScript">
// 监听父窗口发送过来的数据向服务器发送post请求
window.addEventListener("message", function( event ) {
var data = event.data; //接收父窗口传递过来的数据
window.parent.postMessage(res, "*"); //通过postMessage给父窗口发送新的信息
}, false);
</script>
</head>
<body></body>
</html>
[跨域基础知识]简单请求和复杂请求(是否触发预检)
-
简单请求
日常开发中,可以认为满足以下三点的请求为简单请求。- 请求方式为 GET、POST、HEAD
- 只有最常见的请求头
- 比较原始的Content-Type (像application/json 就不行)
-
复杂请求
简单请求之外的都是复杂请求。 -
浏览器对于简单请求的处理过程:
- 浏览器正常发送跨域请求,并在请求头中附加Origin字段标明请求来源。
- 如果服务器不做出跨域的正确响应(添加Access-Control-Allow-Origin等字段),
则浏览器会拦截返回的内容
。 - 服务器正确响应,则一切都照常。
-
对于复杂请求,首先会进行预请求(options)
, 浏览器验证服务端是否允许访问,
若不允许,则正式请求会被浏览器在发送之前拦截。,
如果允许的话,则发送正式请求。 -
对于简单请求,如果服务器没有配置CORS,则简单跨域请求可以成功执行
,
但是返回的内容会被浏览器拦截!
作者:木子水吉_08
链接:https://www.jianshu.com/p/3d8748f85a06
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
参考链接
https://baijiahao.baidu.com/s?id=1628698007235057817&wfr=spider&for=pc