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

跨域问题 #8

Open
SuperTapir opened this issue May 20, 2020 · 0 comments
Open

跨域问题 #8

SuperTapir opened this issue May 20, 2020 · 0 comments
Labels

Comments

@SuperTapir
Copy link
Owner

浏览器的同源策略

同源策略用于限制一个 源的文档或加载的脚本 对于另一个源的资源进行交互。

实际上是为了 安全 作出的策略。

定义同源

两个URL同源 = 两个URL的 protocol port host 都相同

对于 host 这块,特地做了调查,域名必须完全一致,即使是子域名也是不可以的,比如 https://baidu.comhttps://xueshu.baidu.comhttps://music.baidu.com 都不是同源的

源的继承

如何在某页面,通过 window.open 打开 about:blankjavascript:, 那么新打开的页面可以继承之前的源。产生一个同源的关系。

跨源网络访问

同源策略虽然提高了安全性,但是也为开发带来了很多不便,所以前辈们总结了很多跨域的方法来绕过同源策略或者进行安全的跨域访问。

<img/>

由于 html 标签都是可以进行跨域访问的,所以可以通过它来绕过同源策略的限制。

如果想要进行一个 GET 请求,但是又不需要获取请求的响应,那么可以通过 <img/> 解决

const img = new Image();
img.onload = img.onerror = function(){
    console.log("Done!");
};
img.src = "test.html?a=10";

JSONP(JSON with Padding)

这个非常出名,使用量也相当高,可以说是过去解决跨域访问问题的通用方案,并且 JQuery 里也有 JSONP 的请求模式。

JSONP 是利用 <script/> 来获取外部动态产生的 JSON 数据。但利用这种方式直接获取的数据并不是JSON,而是一段 JavaScript 代码,通过这段代码来间接的进行 JSON 数据的获取。


例:

这里我举例说明一下。

<script type="text/javascript" src="http://api.com/getSomething?params=test&callback=foo"></script>

这里是一段 JSONP 的代码,这个 <script/>src 为我们要发起请求的一个 API 地址,注意其中的 query 参数。

  • params: test
  • callback: foo

这里的 callback ,对于JSONP,一般来说是一个特殊的参数。它代表了最后得到数据以后,应该调用什么回调函数来进行接收。

在本例中,当这段 <script/> 解析后,得到的是:

foo({"Name": "小明", "Id" : 1823, "Rank": 7})

这里 foo 的参数,应当是本次请求真正想得到的JSON数据。

这段代码被浏览器解析后,相当于直接执行了这个回调函数,并且也携带了从后端返回的动态参数,实现了一次跨域访问

CORS (Cross-Origin Resource Sharing)

解决跨域访问的终极策略。从服务提供者方面解决问题,利用 Access-Control 系列的 HTTP Headers 来允许和控制对于跨域请求的处理。

规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

简单请求

某些请求不会触发预检,这些请求被视为 “简单请求”(这不是规范的说法)。以下为条件:

  • 方法: GET HEAD POST 三选一
  • Content-Typetext/plain multipart/form-data application/x-www-form-urlencoded 三选一
  • 除了被用户代理自动设置的首部字段(例如 Connection ,User-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合

附带身份凭证的请求

对于跨域的 XHR 或 Fetch 请求,默认不会发送凭证信息(Cookie)。必须 withCredentials 设为 true 才能发送。这时服务器响应中还必须携带 Access-Control-Allow-Credentials: true

另外,如果 Access-Control-Allow-Origin: *,则携带 Cookie 的请求会直接失败。只有该首部为具体的值才能正常使用。

参考

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