zoukankan      html  css  js  c++  java
  • 跨域

    为什么会有跨域?因为浏览器的同源策略。

    同源策略

    源相同。

    如何区别是否是同一个源?

    • 协议相同
      js 中通过 location.protocol 获取协议。
      http、https是不同协议。
    • 端口相同
      js 中通过 location.port 获取端口。
      HTTP 端口默认是 80 。
      HTTPS 端口默认是 443 。
    • 域名相同,包括主域、子域名。
      js 中通过 location.hostname 获取域名。
      http://fanyi.youdao.com。fanyi 是子域,youdao.com 是主域。www.youdao.com 与 youdao.com 也是属于不同的域名。

    同源策略限制了从同一个源加载的文档(document,主要是 dom 相关)或脚本(js,主要指 XMLHttpRequest )如何与来自另一个源的资源进行交互。

    Cookie中的同源只关注域名,忽略协议和端口。

    个人理解主要就是两方面:

    1. 前端与前端的同源限制
      页面中引入 iframe ,iframe 的源是否与当前页的源需要相同。
    2. 前端与后端的同源限制
      前端的页面的源需要与后端提供的接口的源相同。

    如果没有同源策略,会有什么危害?

    • 获取文档中的 dom 信息
      可以利用 iframe 嵌套一些正规网站,除了网址不一样,其他都一样(效果有点类似钓鱼网站,不过钓鱼不是用 iframe ,是做的样式一样)。可以获取用户信息(密码、支付信息等)。
    • CSRF(跨站请求伪造)
      获取其他正规网站的 cookie ,然后用 cookie 模拟用户操作,如支付、转账。

    所以同源策略是一个用于隔离潜在恶意文件的重要安全机制。

    解决跨域通信

    • 前端与前端的跨域
      不同主域的前端页面之间,不能实现互相通信。所以主要解决的是主域相同的,子域不同的互相通信问题。
      • document.domain
        当前页和 iframe 页面都设置相同的 document.domain,则当前页可以拿到 iframe 中的 dom 节点。
        document.domain 只能设置成自身或更高一级的父域,且主域必须相同。
        这种方式非常适用于 iframe 跨域的情况。
      • postMessage
        window.postMessage(message,targetOrigin) 方法是 HTML5 新引进的特性,可以使用它来向其它的 window 对象发送消息,无论这个 window 对象是属于同源或不同源。
        调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。
        需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。
        可以实现双向通信,但是当前页获取不到 iframe 中的 dom 节点。
        当前页:
        iframe:
    • 前端与后端的跨域
      • 代理
        同源的后端去请求获取不同源的数据,再返给同源的前端。
      • JSONP
        主要原理是利用了script 标签可以跨域请求的特性,由其 src 属性发送请求到服务器,服务器返回 JavaScript 代码,浏览器接受响应,然后就直接执行了,这和通过 script 标签引用外部文件的原理是一样的。
        只有 get 方法( script 加载资源就是 get ),前端本地定义方法,返回值为执行该方法,本地定义的方法名称需要和返回值执行的方法名一样。
        后端代码: 前端代码:
      • CORS
        跨源资源共享机制

    CORS

    跨源资源共享机制(Cross-Origin Resource Sharing)允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。浏览器支持在 API 容器中(如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。

    CORS 需要客户端和服务器同时支持。

    跨域资源共享标准

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

    跨域资源共享标准允许在下列场景中使用跨域 HTTP 请求:

    • XMLHttpRequest 或 Fetch 发起的跨域 HTTP 请求。

    • Web 字体 (CSS 中通过 @font-face 使用跨域字体资源)

    • WebGL 贴图

    • 使用 drawImage 将 Images/video 画面绘制到 canvas

    • 样式表

    • scripts

    访问控制场景

    使用三个场景来解释跨域资源共享机制的工作原理。这些例子都使用 XMLHttpRequest 对象。

    简单请求

    某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。

    若请求满足所有下述条件,则该请求可视为“简单请求”:

    • 使用下列方法之一

      • GET

      • HEAD

      • POST

    • Fetch 规范定义了对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段。该集合为:

      • Accept

      • Accept-Language

      • Content-Language

      • Content-Type (需要注意额外的限制)

      • DPR

      • Downlink

      • Save-Data

      • Viewport-Width

      • Width

    • Content-Type 的值仅限于下列三者之一

      • text/plain

      • multipart/form-data

      • application/x-www-form-urlencoded

    • 请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

    • 请求中没有使用 ReadableStream 对象。

    预检请求

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

    当请求满足下述任一条件时,会首先发送预检请求:

    • 使用了下面任一 HTTP 方法

      • PUT

      • DELETE

      • CONNECT

      • OPTIONS

      • TRACE

      • PATCH

    • 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:

      • Accept

      • Accept-Language

      • Content-Language

      • Content-Type (需要注意额外的限制)

      • DPR

      • Downlink

      • Save-Data

      • Viewport-Width

      • Width

    • Content-Type 的值不属于下列之一

      • text/plain

      • multipart/form-data

      • application/x-www-form-urlencoded

    • 请求中的 XMLHttpRequestUpload 对象注册了任意多个事件监听器。

    • 请求中使用了 ReadableStream 对象。

    附带身份凭证的请求

    一般而言,对于跨域 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的 withCredentials 为 true 。

    如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true ,浏览器将不会把响应内容返回给请求的发送者。

    对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“*”。

  • 相关阅读:
    mysql添加索引
    【最短路】道路重建 @upcexam5797
    【数论&想法题】小C的问题 @"科林明伦杯"哈尔滨理工大学第八届程序设计竞赛
    【最大公约数&链表】权值 @upcexam5921
    【组合数】微信群 @upcexam6016
    【二维树状数组】计数问题 @JSOI2009/upcexam5911
    【组合&取补集】数三角形 @CQOI2014/BZOJ3505/upcexam3843
    【LCA&倍增】货物运输 @upcexam5909
    【组合数】[NOIP2011]选择客栈[c++]
    【模拟】[NOIP2011]铺地毯[c++]
  • 原文地址:https://www.cnblogs.com/yayaxuping/p/11059601.html
Copyright © 2011-2022 走看看