如何获取其他域名的数据


theme: condensed-night-purple
highlight: a11y-dark

什么是同源策略

同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。

什么是同源

如果两个 URL 的协议、域名和端口都相同,我们就称这两个 URL 同源。
http://localhost:8888

http://localhost:8888/s

如上例子则为同源

同源策略的作用

不同源的网页,不能共享数据/偷数据

如何进行跨域

我们了解到了浏览器同源策略的作用,也正是有了跨域限制,才使我们能安全的上网。但是在实际工作中,我们需要突破这样的限制,因此下面三种解决方法。

CORS(跨源资源共享)

CORS(跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它源,使得浏览器允许这些 origin 访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。

简单请求

若请求满足所有下述条件,则该请求可视为简单请求(请求不会触发 CORS 预检请求)
使用下列方法之一:

请求方法是以下三种方法之一:

  1. GET
  2. HEAD
  3. POST

HTTP的头信息不超出以下几种字段:

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Last-Event-ID
  5. Content-Type(只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain)

满足上面两个条件,就属于简单请求

简单请求设置方法

假设 a.com:8888 想把 GET /data 共享给 b.com:7777

  1. /data 在响应头设置 Access-Control-Allow-Origin: http://b.com:7777
    if (path === "/data") {
    response.statusCode = 200;
    response.setHeader("Content-Type", "application/json;charset=utf-8");
    response.setHeader("Access-Control-Allow-Origin", "http://b.com:7777");
    response.write(`{"name":"Frank"}`);
    response.end();

预检请求

与简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。”预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://a.com/data');
xhr.setRequestHeader('frank', '18');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<person><name>Arun</name></person>');

上面的代码使用 POST 请求发送一个 XML 请求体,该请求包含了一个非标准的 HTTP frank 请求首部。该请求的 Content-Type 为 application/xml,且使用了自定义的请求首部,所以该请求需要首先发起“预检请求”。

预检请求设置方法

    if (path === "/data") {
    response.statusCode = 200;
    response.setHeader("Content-Type", "application/json;charset=utf-8");
    response.setHeader("Access-Control-Allow-Origin", "http://b.com:7777");
    response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
    response.setHeader("Access-Control-Allow-Hearders", "frank");
    response.write(`{"name":"Frank"}`);
    response.end();

JSONP 跨域

由于<script>标签不受同源策略约束 ,可以请求任意 JS所以后端把数据直接放在 JS 里了

// 1. 定义一个 回调函数 window.xxx 用来接收返回的数据
window.xxx = (data) => {
    console.log(data);
};

// 2. 动态创建一个 script 标签,并且告诉后端回调函数名叫 window.xxx
var body = document.getElementsByTagName('body')[0];
var script = document.gerElement('script');
script.src = 'http://a.com/data?callback=xxx';
body.appendChild(script);

// 3. 通过 script.src 请求 `http://a.com/data?callback=xxx`,
// 4. 后端能够识别这样的 URL 格式并处理该请求,然后返回 window.xxx({"name": "frank"}) 给浏览器
// 5. 浏览器在接收到 window.xxx({"name": "frank"})  之后立即执行 ,也就是执行 window.xxx方法,获得后端返回的数据,这样就完成一次跨域请求了。
JSONP的缺点

<script> 只能发 get 请求

反向代理

一般通过 nginx 配置实现

实现步骤

假设 a.com:8888 想把 GET /data 共享给 b.com:7777

  1. b.com 后端提供一个 /data(Nginx 配置如下)
  2. b.com 前端通过 AJAX 访问 b.com/data
  3. b.com/data 向 a.com/data 发请求,得到响应之后给 b.com 的前端
location /data {
    proxy_pass http://a.com:8888;
}

以上就是三种实现跨域的方法

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容