一文带你了解 HTTP 黑科技( 七 )


  1. Web 字体(用于 CSS 中@ font-face中的跨域字体使用) , 以便服务器可以部署 TrueType 字体 , 这些字体只能由允许跨站点加载和使用的网站使用 。
  2. WebGL 纹理
  3. 使用 drawImage() 绘制到画布上的图像/视频帧
  4. 图片的 CSS 形状
跨域功能概述跨域资源共享标准通过添加新的 HTTP 标头来工作 , 这些标头允许服务器描述允许哪些来源从 Web 浏览器读取信息 。另外 , 对于可能导致服务器数据产生副作用的 HTTP 请求方法(尤其是 GET 或者具有某些 MIME 类型 POST 方法以外 HTTP 方法) , 该规范要求浏览器预检请求 , 使用 HTTP OPTIONS 请求方法从服务器请求受支持的方法 , 然后在服务器批准后发送实际请求 。服务器还可以通知客户端是否应与请求一起发送凭据(例如 Cookies 和 HTTP 身份验证) 。
注意:CORS 故障会导致错误 , 但是出于安全原因 , 该错误的详细信息不适用于 JAVAScript 。所有代码都知道发生了错误 。确定具体出问题的唯一方法是查看浏览器的控制台以获取详细信息 。
访问控制下面我会和大家探讨三种方案 , 这些方案都演示了跨域资源共享的工作方式 。所有这些示例都使用XMLHttpRequest , 它可以在任何支持的浏览器中发出跨站点请求 。
简单请求一些请求不会触发 CORS预检(关于预检我们后面再介绍) 。简单请求是满足一下所有条件的请求
  • 允许以下的方法:GET、HEAD和 POST
  • 除了由用户代理自动设置的标头(例如 Connection、User-Agent 或者在 Fetch 规范中定义为禁止标头名称的其他标头)外 , 唯一允许手动设置的标头是那些 Fetch 规范将其定义为 CORS安全列出的请求标头  , 它们是:AcceptAccept-LanguageContent-LanguageContent-Type(下面会介绍)DPRDownlinkSave-DataViewport-WidthWidth
  • Content-Type 标头的唯一允许的值是application/x-www-form-urlencodedmultipart/form-datatext/plain
  • 没有在请求中使用的任何 XMLHttpRequestUpload 对象上注册事件侦听器;这些可以使用XMLHttpRequest.upload 属性进行访问 。
  • 请求中未使用 ReadableStream对象 。例如 , 假定 web 内容 https://foo.example 想要获取 https://bar.other 域的资源 , 那么 JavaScript 中的代码可能会像下面这样写const xhr = new XMLHttpRequest(); const url = 'https://bar.other/resources/public-data/'; xhr.open('GET', url); xhr.onreadystatechange = someHandler; xhr.send();
这使用 CORS 标头来处理特权 , 从而在客户端和服务器之间执行某种转换 。
一文带你了解 HTTP 黑科技

文章插图
 
让我们看看在这种情况下浏览器将发送到服务器的内容 , 并让我们看看服务器如何响应:
GET /resources/public-data/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateConnection: keep-aliveOrigin: https://foo.example注意请求的标头 Origin  , 它表明调用来自于 https://foo.example 。让我们看看服务器是如何响应的
HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 00:23:53 GMTServer: Apache/2Access-Control-Allow-Origin: *Keep-Alive: timeout=2, max=100Connection: Keep-AliveTransfer-Encoding: chunkedContent-Type: application/xml[…XML Data…]服务端发送 Access-Control-Allow-Origin 作为响应 。使用 Origin 标头和 Access-Control-Allow-Origin 展示了最简单的访问控制协议 。在这个事例中 , 服务端使用 Access-Control-Allow-Origin 作为响应 , 也就说明该资源可以被任何域访问 。
如果位于https://bar.other的资源所有者希望将对资源的访问限制为仅来自https://foo.example的请求 , 他们应该发送如下响应
Access-Control-Allow-Origin: https://foo.example现在除了 https://foo.example 之外的任何域都无法以跨域方式访问到 https://bar.other 的资源 。
预检请求和上面探讨的简单请求不同 , 预检请求首先通过 OPTIONS 方法向另一个域上的资源发送 HTTP 请求 , 用来确定实际请求是否可以安全的发送 。跨站点这样被预检 , 因为它们可能会影响用户数据 。
下面是一个预检事例
const xhr = new XMLHttpRequest();xhr.open('POST', 'https://bar.other/resources/post-here/');xhr.setRequestHeader('X-PINGOTHER', 'pingpong');xhr.setRequestHeader('Content-Type', 'application/xml');xhr.onreadystatechange = handler;xhr.send('<person><name>Arun</name></person>');


推荐阅读