HTTP(二)、跨域资源共享(CORS)

22 篇文章 0 订阅
7 篇文章 0 订阅

2.跨域资源共享(CORS)

跨域简介

当访问一个资源文件时,如果从非该资源文件所在的服务器不同域名或者端口处进行访问时,该资源会发起一个跨域请求。

例如,网站A的地址是http://www.domain-a.com ,该网站中HTML页面通过 img 标签中的 src 属性请求http://www.domain-b.com/static/xxx.png 图片资源,此时,就发生了跨域请求。

处于安全考虑,浏览器限制从脚本内发起的跨域资源请求。例如,XHR和Fetch的API遵循同源策略。这意味着使用这些API只能从同一个域才能请求资源文件。

需要注意的是,跨域不一定是浏览器限制了发起跨域请求,也可能是跨域请求可以正常发起,但是返回的数据被浏览器截获。

最好的例子就是CSRF跨站攻击,有些浏览器不允许从HTTPS的网站跨域访问HTTP, 比如Chorme 和 Firefox,这些浏览器在请求还未发出时就会拦截请求。
这里写图片描述

CORS 机制允许Web 服务器对跨域访问进控制,从而保证跨域数据传输安全进行。目前浏览器都支持该机制,不过需要跨域访问需要客户端和服务端同时支持。

服务端支持CORS

浏览器会针对XHR和Fetch中发起的跨域请求发送特殊的HTTP header 请求头信息。并且服务端也必须返回允许使用特定的跨域响应的header 头信息。

详细链接

跨域访问常见场景

  • XHR 或者 Fetch 发起的跨域HTTP请求
  • Web 字体(通过CSS 中的@font-face使用跨域字体)
  • 使用drawImageimage/video画面绘制到canvas
  • script

跨域资源共享(CROS)

CORS标准新增了一组HTTP首部字段,允许服务器声明哪些请求源有权限访问哪些资源。另外,规范要求,那些可能导致服务器产生隐患的HTTP请求方法(除GET之外的请求),浏览器必须首先使用OPTIONS方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务端返回允许响应后,才发起实际的HTTP请求。在预检请求的返回中,服务端也可以通知客户端,是否需要携带身份凭证(cookies和HTTP认证相关数据)。

跨域共享实践

这里,我们通过XHR对象介绍三个跨域资源共享的实例。

1. 简单请求

简单请求的特征:

  • 不会触发预检请求
  • 使用以下方法之一
    • GET
    • HEAD
    • POST
  • Fetch 规范定义,不得自定义下面header之外的其他首部字段

    • Accept
    • Accept-Language
    • Content-Language
    • Conetent-Type
    • Viewport-width
  • Content-Type的值为下列之一

    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded
  • 请求中任意XMLHttpRequestUpload对象均没有注册任何事件监听器

  • 请求中没有使用ReadableStream对象

客户端和服务端之间使用CORS首部字段处理跨域权限:

这里写图片描述

查看一个跨域请求实例:

这里写图片描述

服务端返回的 Access-Control-Allow-Origin: * 表明该资源可以被任意域名访问,不收跨域限制。

2.预检请求

预检请求要求必须首先使用OPTIONS 方法发起一个预检请求到服务端,来获知服务端是否允许该实际请求。

预检请求的满足条件:

  • 使用以下任意一种HTTP方法
    • PUT
    • DELETE
    • CONNECT
    • OPTIONS
    • TRACE
    • PATCH
  • 人为设置以下集合之外的首部字段。该集合为:
    • Accept
    • Accept-Language
    • Content-Language
    • Conetent-Type
    • Viewport-width
  • Content-Type 的值不属于以下之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 请求中任意XMLHttpRequestUpload对象注册多个事件监听器
  • 请求中使用了ReadableStream对象

OPTIONS 请求

这里写图片描述

POST 请求

这里写图片描述

执行过程:

浏览器首先检查到,JS发起的请求需要被预检。Request Method:OPTIONS表示这个是一个预检请求,该方法不会对服务器资源产生影响,预检请求中同时携带了下面两个首部字段:

Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

首部字段Access-Control-Request-Method通知服务端,实际请求将使用POST方法。
首部字段Access-Control-Request-Headers通知服务端,实际请求将携带Content-Type字段。
服务端根据预检头信息,判断实际请求是否被允许。

附带凭证的请求

通常情况下,浏览器发送跨域请求时不会发送身份凭证信息,如果要发送凭证信息的话,就要在对XHR对象设置特殊的标志位。

这里写图片描述

本例中,我们对XHR对象的withCredentials标置设置为true,从而可以向跨域的服务器发送Cookies信息。

附带身份凭证的请求不得设置通配符

对于带凭证的请求,服务端不可将Access-Control-Allow-Origin值设置为“*”。

这是因为请求的首部中携带Cookie信息,如果设置为“*”,请求将会失败。将Access-Control-Allow-Origin值设置为请求方的host,则请求执行成功。

HTTP跨域请求首部字段

1.Origin

Origin 表明了首部字段预检请求或实际请求的源端。

Origin: <origin>

2. Access-Control-Request-Method

Access-Control-Request-Method 首部字段用于预检请求。作用是通知实际请求使用的HTTP方法。

Access-Control-Request-Method:<method>

3.Access-Control-Request-Headers

Access-Control-Request-Headers 收不自动用于预检请求。做用户通知实际请求中携带的首部字段通知给服务端。

Access-Control-Request-Headers:<field-name>

HTTP跨域响应首部字段

1.Access-Control-Allow-Origin

Access-Control-Allow-Origin: <origin> | *

orgin参数允许指定外域URI访问指定资源。对于不需要携带身份凭证的请求,服务端可以指定该字符为通配符,它允许来自所有域的访问。

如果,允许接收指定一个具体的域请求时

Access-Control-Allow-Origin: http://google.com

服务端指定的时一个具体的域而不是“*”,那么响应的首部中Vary字段值必须包含 Origin 。这将告诉客户端:服务器对不同源站返回不同的内容。

2.Access-Control-Expose-Headers

服务端将浏览器允许访问的头放入白名单,例如:

Access-Control-Expose-Headers: x-header

这样,浏览器就可以根据服务端的响应头白名单进行访问。

3.Access-Control-Max-Age

指明该预检请求可以被缓存多久。

4.Access-Control-Allow-Credentials

当浏览器的credentials设置为true时,是否允许浏览器读取response内容。

Access-Control-Allow-Credentials: true

5.Access-Control-Allow-Methods

指明浏览器实际允许使用的HTTP方法。

Access-Control-Allow-Methods: <methods>

6. Access-Control-Allow-Headers

指明浏览器实际允许携带的首部字段。

Access-Control-Allow-Headers: <filed-name>
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值