跨域和CORS

  1. 什么是跨域?前端

    同源:协议、域名、端口相同。不一样源便是跨域。两个不一样的域名即便指向同一个IP地址,也不一样源。nginx

  2. 同源策略限制的内容有哪些?json

    DOM 层面:限制了不一样源 JavaScript 对当前 DOM 对象的读写操做;canvas

    数据层面:限制了不一样源站点读取当前站点的 Cookie、IndexDB、LocalStorage 等数据;segmentfault

    网络层面:限制了经过 XMLHttpRequest 等方式将站点的数据发送给不一样源的站点。跨域

  3. 容许跨域的三个标签浏览器

    <img><link><script>服务器

  4. 跨域的解决方案有哪些?网络

    (1) 同源策略限制下请求接口的方式:app

    1. JSONP

      • 首先是利用<script>标签的src属性来实现跨域。
      • 经过将前端方法做为参数传递到服务器端,而后由服务器端注入参数以后返回,实现服务器端向客户端通讯。
      • 因为使用<script>标签的src属性,所以只支持 get 方法。
    2. iframeform

      • 建立一个iframe元素和form元素;
      • 若是须要在响应返回时执行一些操做,能够在iframeload事件处理程序中添加相应代码;
      • 指定form元素的action属性为请求的urlmethod属性为posttarget属性为iframename,最后调用formsubmit()方法发送请求。
    3. CORS

      分为简单请求和应当先发送预检请求的请求。简单请求设置Origin头部,服务器返回响应数据时设置Access-Control-Allow-Origin头部。非简单请求先发送预检请求,预检请求完成后再发送实际请求。

    4. 代理

      使用nginx代理配置 server_name 为请求发起方的域名,而后设置location拦截前端的跨域请求,再将请求代理到服务器域名便可绕过浏览器的同源策略。

    5. WebSocket

    (2) 同源限制下Dom查询的方式

    1. postMessage

      使用 HTML5 提供的postMessage()方法能够实现不一样页面的跨域通信。在页面中使用postMessage()发送消息,使用addEventListener()监听回复的消息。

    2. document.domain

      适用于主域名相同,子域名不一样的iframe跨域。给两个页面指定document.domain = 主域名便可访问对方的window对象了。

    3. canvas操做图片的跨域问题

      跨域的图片只要能在网页中正常显示,就可使用canvasdrawImage()方法绘制出来。可是若是要对图片进行getImageData()toDataURL()操做,则须要处理跨域问题。

      • 响应头中设置Access-Control-Allow-Origin头部,容许请求发送方访问
      • 建立了Image实例后,设置实例的crossOrigin属性值为''crossOrigin的属性值不为use-credentials时,所有都会解析为anonymous,表示不须要携带任何非匿名信息给服务器)
  5. 什么是 CORS ?

    CORS 即跨域资源共享标准,它新增了一组 HTTP 首部字段,容许服务器声明哪些源站经过浏览器有权限访问哪些资源。另外,对可能对服务器数据产生反作用的 HTTP 请求方法,浏览器必须先使用OPTIONS方法发起一个预检请求,从而获知服务端是否容许该跨域请求。服务器确认容许以后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也能够通知客户端,是否须要携带身份凭证。

  6. CORS 的三个访问控制场景

    (1) 简单请求知足如下全部条件:

    1. 使用的请求方法为GETHEADPOST中的一种;

    2. 首部字段仅限于AcceptAccept-LanguageContent-LanguageContent-TypeDPRDownlinkSave-DataViewport-WidthWidth所组成的集合中的元素;

    3. Content-Type值为text/plainmultipart/form-dataapplication/x-www-form-urlencoded中的一个;

    4. 请求中的任意XMLHttpRequestUpload对象都没有注册任何事件监听器;

    5. 请求中没有使用ReadableStream对象。

      简单请求中头部字段Origin值为本身的域名,响应头部携带字段Access-Control-Allow-Origin,值为包含请求域名的值或*,这样便可完成跨域请求。

    (2) 应当先发送预检请求的请求知足下述任一条件:

    1. 使用的请求方法为PUTDELETECONNECTOPTIONSTRACEPATCH中的一种;
    2. 首部字段设置了AcceptAccept-LanguageContent-LanguageContent-TypeDPRDownlinkSave-DataViewport-WidthWidth以外的字段;
    3. Content-Type值不属于application/x-www-form-urlencodedmultipart/form-datatext-plain之一;
    4. 请求中的XMLHttpRequestUpload对象注册了任意多个事件监听器;
    5. 请求中使用了ReadableStream对象。

    发送一个使用OPTIONS方法的预检请求,用以从服务器获取更多信息。预检请求完成以后,发送实际请求。

    // 预检请求头部,这些头部无须手动设置,使用XMLHttpRequest对象发起跨域请求时,它们已经被设置就绪
    Origin: 请求来源
    Access-Control-Request-Method: 实际请求将使用的方法
    Access-Control-Request-Headers: 实际请求将使用的自定义首部字段
    
    // 预检请求响应头部
    Access-Control-Allow-Origin: 容许访问的域名
    Access-Control-Allow-Methods: 容许使用的请求方法
    Access-Control-Allow-Headers: 容许使用的自定义首部
    Access-Control-Max-Age: 响应的有效时间。在有效时间内,浏览器无须为同一请求再次发起预检请求
    复制代码

    (3) 附带身份凭证的请求

    • 跨域请求须要发送凭证信息时,XMLHttpRequest请求须要将withCredentials标识设置为trueFetch请求须要将credentials: 'include'添加到fetch()方法的init对象中。响应头部中须要携带Access-Control-Allow-Credentials: true头部,不然浏览器不会把响应内容返回给请求发送者。
    • 附带凭证的请求,服务器不能够设置Access-Control-Allow-Origin的值为*,若是设置了会致使请求失败。

参考:

  1. 【segmentfault】不要再问我跨域的问题了:segmentfault.com/a/119000001…
  2. 解决canvas图片getImageData, toDataURL跨域问题:www.zhangxinxu.com/wordpress/2…
  3. 【MDN】HTTP访问控制(CORS):developer.mozilla.org/zh-CN/docs/…
相关文章
相关标签/搜索