跨域/同源笔记
2019-05-07 本文已影响0人
fejavu
同源策略
浏览器出于安全考虑,只允许本域下接口交互,不同源的客户端脚本在没有明确授权下,不能读写对方的资源。
- 同协议,如http或者https
- 同域名,如都是google.com/index.html,google.com/another
- 同端口,80端口
同源例子:
google.com/ai,google.com/bigdata
不同源例子:
- http://google.com/main.js-https://google.com/another.php(协议不同)
- https://google.com/main.js-https://facebook.com/another.php(域名不同)
- https://google.com/main.js-https://google.com:80/another.php(端口不同)
跨域方法
JSONP
以 script 标签加载数据的方式绕过同源策略,后端返回数据时拼接函数,将返回数据作为拼接函数的参数,数据返回后执行该函数。
<script>
showData(string) {
console.log(JSON.parse(string));
}
</script>
<script
src="http://google.com/ai.js?callback = showData">
</script>
CORS
CORS,cross-origin resourse sharing,支持现在浏览器,IE10以上。
在后端加上这句话:
// allow all request of cross origin
res.setHeader('Access-Control-Allow-Origin','*');
// allow only the request of 'example.com:8080'
res.setHeader('Access-Control-Allow-Origin','example.com:8080');
postMessage
iframe 域名和当前域名跨域。
$('.main input').addEventListener('input', function() {
windows.parent.postMessage(this.value, '*');
})
window.addEventListener('message', function(e) {
$('#input').value = e.data;
console.log(e.data);
})
实践检验
在本地写一个html,地址是 http://localhost/index.html,
,放置一个 button,点击后向http://127.0.0.1:80请求,此时两个文件不同域名,因此处于跨域,运用 CORS,cross-origin resourse sharing 方法,通过服务器端设置一个跨域允许,从而将服务器端数据返回到不同源请求。
html 客户端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button>show something</button>
<script>
function $(selector) {
return document.querySelector(selector);
}
$('button').onclick = function() {
console.log('clicked');
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:80/getst',true);
xhr.send();
xhr.onload = function(){
var resP = document.createElement('p');
resP.innerHTML = JSON.parse(xhr.responseText)
$('body').appendChild(resP);
// console.log(JSON.parse(xhr.responseText));
}
}
</script>
</body>
</html>
server 端
var http = require('http');
var fs = require('fs');
var path = require('path');
var url = require('url');
http.createServer(function(req, res) {
var pathObj = url.parse(req.url,true);
switch(pathObj.pathname) {
case '/getst':
var something = "This is a cross origin response via a request";
res.setHeader('Access-Control-Allow-Origin', 'http://localhost');
res.end(JSON.stringify(something));
break;
default:
fs.readFile(path.join(__dirname,pathObj.pathname), function(e,data){
if(e){
res.writeHead(404,'not found');
res.end("<h1>404 Not Found</h1>");
}else {
res.end(data);
}
})
}
}).listen(80);

可以看到,请求的客户端域名是:localhost/index.html,而请求的地址是:http://127.0.0.1:80,两者是跨域的,而在服务器端设置
res.setHeader('Access-Control-Allow-Origin', 'http://localhost');
就是允许http://localhost进行跨域请求,因此请求成功。如果将这行去掉,这回造成非同源拦截:
