同源策略
浏览器出于安全策略的考虑,只允许与本域下的接口交互。
本域指:
- 同协议
- 同域名
- 同端口
跨域的几种方式
1. JSONP
原理:利用html中script标签的src请求可以跨域获取资源,通过前端传递回调函数,后端用回调函数包裹数据并返回给前端,最后再由前端调用函数获取数据。
代码示例
// 前端
<script>
var script = document.createElement('script');
script.src = 'http://127.0.0.1:8080/JSONP?callback=_callback';
document.body.appendChild(script);
document.body.removeChild(script)
// 回调函数
var _callback = function (obj) {
for (key in obj) { c
onsole.log('key: ' + key + ' value: ' + obj[key]);
}
}
</script>
//后端
var express = require('express')
var app = express()
const port = '8080'
app.get('/JSONP',(req,res,next) => {
let callback = req.query.callback
let obj ={
type:'jsonp',
name:'lee'
}
res.writeHead(200,{"Content-Type": "text/javascript"});
res.end(`${callback}(${JSON.stringify(obj)})`)
})
app.listen(port)
console.log(`服务器地址为: http://localhost:${port}`);
JSONP跨域需要后端有对应接口
2. CORS
介绍:跨域资源共享是一种当前域的资源被其他域访问的机制
原理:当使用 XMLHttpRequest 发送请求时,浏览器如果发现违反了同源策略就会自动加上一个请求头 origin,后端在接受到请求后确定响应后会在 Response Headers 中加入一个属性 Access-Control-Allow-Origin,值就是发起请求的源地址,浏览器得到响应会进行判断 Access-Control-Allow-Origin 的值是否和当前的地址相同,只有匹配成功后才可以拿到相应数据
通过Hostbuddy修改
127.0.0.1 a.com
启动http-server,打开http://a.com:8081/CORS.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>cros</title>
</head>
<body>
</body>
<script>
let xhr = new XMLHttpRequest()
xhr.open('GET','http://a.com:8080/CROS',true)
xhr.send()
xhr.onload= function(){
console.log(xhr.status);
console.log(xhr.responseText);
}
</script>
</html>
而服务器启动在来8080端口
app.get('/CROS',(req,res) => {
console.log('CROS');
let obj = {
type:'cros',
name:'lee'
}
res.writeHead(200,{
"Content-Type":"text/html;charset=UTF-8",
"Access-Control-Allow-Origin":'http://a.com:8081'
//"Access-Control-Allow-Origin":'http://127.0.0.1:8081'
// "Access-Control-Allow-Origin":'http://b.com:8081'
})
res.end(JSON.stringify(obj))
})
只有http://a.com:8081成功了,"Access-Control-Allow-Origin":*
查看浏览器origin
Request Header中
Origin: http://a.com:8081
与
Response Header中的
Access-Control-Allow-Origin: http://a.com:8081
一致
3. 降域
使用
例子:
http://a.lcb.com:8080/a.html
http://b.lcb.com:8080/b.html
父域名相同,只要使用
document.domain = 'lcb.com'
指定到父域,即可实现跨域
4. messagePost
父窗口
// http://a.com:8081/postMessage.html
<!-- 通过 iframe 嵌入子页面 -->
<iframe src="http://a.com:8082/other-domain.html"
id="otherPage"></iframe>
<br/><br/>
<input type="text" id="message"><input type="button"
value="Send to child.com" onclick="sendIt()" />
<script type="text/JavaScript">
function sendIt(){
// 通过 postMessage 向子窗口发送数据
document.getElementById("otherPage").contentWindow
.postMessage(
document.getElementById("message").value,
"http://a.com:8082"
);
}
</script>
子窗口
// http://a.com:8082/other-domain.html
<body>
Web page from http://localhost:8082
<div id="content"></div>
</body>
<script type="text/JavaScript">
//event 参数中有 data 属性,就是父窗口发送过来的数据
window.addEventListener("message", function( event ) {
// 把父窗口发送过来的数据显示在子窗口中
document.getElementById("content").innerHTML+=event.data+"<br/>";
}, false );
</script>
网友评论