Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

跨域问题总结 #7

Open
MLuminary opened this issue May 8, 2018 · 0 comments
Open

跨域问题总结 #7

MLuminary opened this issue May 8, 2018 · 0 comments
Labels

Comments

@MLuminary
Copy link
Owner

跨域问题总结

跨域问题是日常中必须要面对的,每次面试必考跨域也体现了跨域技术的重要性,跨域的文章也多的数不过来,今天这篇文章主要是用来总结自己每种跨域技术的尝试,如果有幸能帮到别人那就再好不过了

自己用 node 搭了两个服务器,前台设置的端口为 3002,模拟的服务端设置的端口为 3001

跨域问题的出现是由于「同源策略」引起的,「同源」就指的是三个相同,即「协议相同」、「域名相同」、「端口相同」,「同源策略」使得以下三种行为受到限制

  • Cookie、LocalStorage 和 IndexDB 无法获取
  • DOM 无法获取
  • Ajax 请求无法发送

具体情况还请移步浏览器同源政策及其规避方法

自己在这还是稍微总(jie)结(jian)一下,写一遍加深一下印象

对于 Cookie 和 iframe

对于 Cookie 和 iframe ,如果两个网页一级域名相同,只是二级域名不同,比如 a.hutchins.comb.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 标签,然后用 scriptsrc 属性引用外部跨域链接,通过回调函数参数接受后台传递的信息

//原生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();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant