跨域问题总结
MLuminary opened this issue · 0 comments
MLuminary commented
跨域问题总结
跨域问题是日常中必须要面对的,每次面试必考跨域也体现了跨域技术的重要性,跨域的文章也多的数不过来,今天这篇文章主要是用来总结自己每种跨域技术的尝试,如果有幸能帮到别人那就再好不过了
自己用 node 搭了两个服务器,前台设置的端口为 3002,模拟的服务端设置的端口为 3001
跨域问题的出现是由于「同源策略」引起的,「同源」就指的是三个相同,即「协议相同」、「域名相同」、「端口相同」,「同源策略」使得以下三种行为受到限制
- Cookie、LocalStorage 和 IndexDB 无法获取
- DOM 无法获取
- Ajax 请求无法发送
具体情况还请移步浏览器同源政策及其规避方法
自己在这还是稍微总(jie)结(jian)一下,写一遍加深一下印象
对于 Cookie 和 iframe
对于 Cookie 和 iframe ,如果两个网页一级域名相同,只是二级域名不同,比如 a.hutchins.com
和 b.hutchins.com
,浏览器可通过设置相同的 document.domain
document.domain = 'hutchins.com';
服务器也可以在设置 Cookie 的时候,指定 Cookie 的所属域名为一级域名,比如
Set-Cookie: key=value; domain=hutchins.com; path=/
这样的话二级域名和三级域名不做任何设置就可以读取这个 Cookie
window.postMessage
H5 引入了全新的 API :「跨文档通信 API」
otherWindow.postMessage(message, tragetOrigin);
otherWindow
窗口message
要发送的信息targetOrigin
指定哪些窗口可以接受到信息,*
表示无限制
接收窗口通过 message
方法接收
window.addEventListener('message' function(e) {
})
message
的事件对象有以下三个属性
- event.source 发送消息的窗口
- event.origin 消息发向的网址
- event.data 发送的消息
AJAX 跨域
jsonp 跨域
jsonp 的原理就是动态创建 script
标签,然后用 script
的 src
属性引用外部跨域链接,通过回调函数参数接受后台传递的信息
//原生js
var script = document.createElement('script');
script.type = 'text/javascript';
//传参并指定回调函数执行函数为onBack
script.src = 'http://localhost:3001/api/jsonp?uname=hutchins&callback=onBack';
document.body.appendChild(script);
//回调执行函数
function onBack(res) {
console.log(JSON.stringify(res));
}
//利用jquery ajax
$.ajax({
url: 'http://localhost:3001/api/jsonp?uname=hutchins',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: 'onBack', // 自定义回调函数名
data: {},
success: function(data) {
console.log(data);
}
});
//node 后台处理前端请求的函数
module.exports = {
//jsonp
jsonpf: function(req, res) {
var params = req.query;
var fn = req.query.callback;
res.writeHead(200, { 'Content-Type': 'text/javascript' });
res.write(fn + '(' + JSON.stringify(params) + ')');
res.end();
}
};
但是 jsonp 只能支持 Get 请求
跨域资源共享 「CORS」
请求分为「简单请求」和「非简单请求」,而处理这两种请求的方式很不同,这里只说一下「简单请求」
请求方式为以下几种
- HEAD
- GET
- POST
HTTP 的消息头不超出以下几种字段
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type 只限于 application/x-www-form-ulrencoded、multipart/form-data、text/plain
// 原生js
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new XDomainRequest(); //兼容 IE8/9
}
//前端设置 cookie
xhr.withCredentials = true;
xhr.open('post', 'http://localhost:3001/api/cors', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('uname=hutchins');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
};
//跨域后台设置
res.writeHead(200, {
'Access-Control-Allow-Credentials': 'true', //后端允许发送 cookie
'Access-Control-Allow-Origin': 'http://localhost:3002'
// 'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly的作用是让js无法读取cookie
});
res.write(JSON.stringify(postData));
res.end();