zoukankan      html  css  js  c++  java
  • 跨域1-CORS跨域

    1.跨域:
    请求的资源和当前网站的,协议/域名/端口 不一样,会发起跨域HTTP请求

    2.为什么会跨域
    出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。 例如,XMLHttpRequest和Fetch API遵循同源策略。
    只能从同一个域中请求HTTP资源,除非使用CORS头文件。

    3.如何跨域:
    CORS(cross origin resource share),跨域(源)资源共享
    a. CORS 需要客户端和服务器同时支持。目前,所有浏览器都支持该机制。

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

    b.简单请求:某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”

    简单请求条件:
    使用方法:GET/POST/OPTION
    
    使用的首部字段集合:
    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
    sample:
    站点http://a.example 的网页应用想访问http://b.example 的资源, 
    http://a.example 的网页中包含的代码:
    
    var request = new XMLHttpRequest();
    var url = 'http://b.example/resources/public-data/';
       
    function callOtherDomain() {
      if(request) {    
        request.open('GET', url, true);
        request.onreadystatechange = handler;
        request.send(); 
      }
    }
    使用 Origin 和 Access-Control-Allow-Origin 就能完成最简单的访问控制。本例中,服务端返回的 Access-Control-Allow-Origin: * 表明,该资源可以被任意外域访问。如果服务端仅允许来自 http://a.example 的访问,该首部字段的内容如下:
    
    Access-Control-Allow-Origin: http://a.example

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

    当请求满足下述任一条件时,即应首先发送预检请求:
    使用了下面任一 HTTP 方法:
    PUT
    DELETE
    CONNECT
    OPTIONS
    TRACE
    PATCH
    
    人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
    Accept
    Accept-Language
    Content-Language
    Content-Type (but note the additional requirements below)
    DPR
    Downlink
    Save-Data
    Viewport-Width
    Width
    
     Content-Type 的值不属于下列之一:
    application/x-www-form-urlencoded
    multipart/form-data
    text/plain
    sample
    var invocation = new XMLHttpRequest();
    var url = 'http://bar.other/resources/post-here/';
    var body = '<?xml version="1.0"?><person><name>Arun</name></person>';
        
    function callOtherDomain(){
      if(invocation)
        {
          invocation.open('POST', url, true);
          invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
          invocation.setRequestHeader('Content-Type', 'application/xml');
          invocation.onreadystatechange = handler;
          invocation.send(body); 
        }
    }


    1.首先使用OPTIONS发起预检请求,预检请求中同时携带了下面两个首部字段:
    Origin: http://foo.example
    Access-Control-Request-Method: POST
    Access-Control-Request-Headers: X-PINGOTHER

    首部字段 Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法。首部字段 Access-Control-Request-Headers 告知服务器,实际请求将携带两个自定义请求首部字段:X-PINGOTHER 与 Content-Type。服务器据此决定,该实际请求是否被允许。

    2.服务器响应预检请求
    Access-Control-Allow-Origin: http://foo.example
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
    Access-Control-Max-Age: 86400

    首部字段 Access-Control-Allow-Methods 表明服务器允许客户端使用 POST, GET 和 OPTIONS 方法发起请求。
    首部字段 Access-Control-Allow-Headers 表明服务器允许请求中携带字段 X-PINGOTHER 与 Content-Type。
    最后,首部字段 Access-Control-Max-Age 表明该响应的有效时间为 86400 秒,也就是 24 小时。在有效时间内,浏览器无须为同一请求再次发起预检请求。浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。


    3.附带身份凭证的请求
    对于跨域 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的某个特殊标志位

    sample
    本例中,http://foo.example 的某脚本向 http://bar.other 发起一个GET 请求,并设置 Cookies:
    var request = new XMLHttpRequest();
    var url = 'http://bar.other/resources/credentialed-content/';

    function callOtherDomain(){
    if(request) {
    request.open('GET', url, true);
    request.withCredentials = true;
    request.onreadystatechange = handler;
    request.send();
    }
    }

    XMLHttpRequest 的 withCredentials 标志设置为 true,从而向服务器发送 Cookies。如果服务器端的响应需要携带 Access-Control-Allow-Credentials: true ,浏览器将把响应内容返回给请求的发送者。

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

    d.HTTP 响应首部字段

    Access-Control-Allow-Origin:
    Access-Control-Allow-Origin: <origin> | *
    origin 参数的值指定了允许访问该资源的外域 URI

    Access-Control-Expose-Headers
    跨域访问时,XMLHttpRequest对象的getResponseHeader()方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置本响应头

    Access-Control-Max-Age
    指定了preflight请求的结果能够被缓存多久

    Access-Control-Allow-Credentials
    指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容。

    Access-Control-Allow-Methods
    首部字段用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法。

    Access-Control-Allow-Headers
    首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段。

    e.HTTP 请求首部字段

    Origin 首部字段表明预检请求或实际请求的源站。
    origin 参数的值为源站 URI。它不包含任何路径信息,只是服务器名称。
    注意,不管是否为跨域请求,ORIGIN 字段总是被发送。

    Access-Control-Request-Method
    Access-Control-Request-Method 首部字段用于预检请求。其作用是,将实际请求所使用的 HTTP 方法告诉服务器。

    Access-Control-Request-Headers
    首部字段用于预检请求。其作用是,将实际请求所携带的首部字段告诉服务器。

  • 相关阅读:
    OPENGL ES2.0如何不使用glActiveTexture而显示多个图片
    OpenGL帧缓存对象(FBO:Frame Buffer Object)
    EGLImage与纹理
    Android下Opengl ES实现单屏幕双眼显示
    comet4j开发指南
    tmp
    Ubuntu16.04下编译android6.0源码
    ubuntu下配置安装conky
    Qt编程之QImage类小结
    Linux学习,在线版
  • 原文地址:https://www.cnblogs.com/bg57/p/8562063.html
Copyright © 2011-2022 走看看