• Ajax 跨域 异步 CORS


    HTTP access control (CORS)
    核心在于使用定制(添加新的header)HTTP header让浏览器和服务器有更多的相互了解,从而决定一个请求或者响应成功还是失败
     
    对于一个简单的请求,没有定制header并且body是text/plain的话,该请求发送的时候会带上一个header叫origin,包含了发送请求的(prototype,domin,和port),服务器就可以根据这个来决定是否响应:
    Origin: http://www.haha.com
     
    当服务器响应的时候,会返回一个Access-Control-Allow-Origin头,里面的信息要么和发送的的origin一样,要么为*如果那是一个公共资源,浏览器匹配以后才会进行处理:
    Access-Control-Allow-Origin: http://www.haha.com
     
    IE跨域:
    通过XDomainRequest对象实现,和XHR比有一些不同之处:
    1、Cookies are neither sent with requests nor received with responses.
    2、There is no access to set request headers other than Content-Type.
    3、There is no access to response headers.
    4、Only GET and POST requests are supported.
    上面这些限制缓解了跨网站伪造请求(csrf)和跨网站脚本攻击(xss),被请求的资源可以根据恰当的数据(user-agent,referrer等等),动态地决定是否设置返回的 Access-Control-Allow-Origin头信息。作为请求的一部分,origin头信息携带着请求发起源域名信息也会被同时发送,这样被请求的资源服务方就可以识别出这是一个XDR跨域请求了。
     
    get请求例子
    var xdr = new XDomainRequest();
    xdr.onload = function(){
    alert(xdr.responseText);
    };
    xdr.onerror = function(){
    alert(“An error occurred.”);
    };
    xdr.timeout = 1000;
    xdr.ontimeout = function(){
    alert(“Request took too long.”);
    };
    xdr.open(“get”, “http://www.somewhere-else.com/page/”);     这里只接受两个参数,只能使用异步方式请求
    xdr.send(null);
    xdr.abort();          //stop the request
    当收到响应的时候,只能拿到未经处理的text。也不能判断status的值。如果没有 Access-Control-Allow-Origin也会失败,并且无法得到错误信息,所以必须监听error事件,不然失败了都没人知道啊。
     
     
    post请求方式:
    var xdr = new XDomainRequest();
    xdr.onload = function(){
    alert(xdr.responseText);
    };
    xdr.onerror = function(){
    alert(“An error occurred.”);
    };
    xdr.open(“post”, “http://www.somewhere-else.com/page/”);
    xdr.contentType = “application/x-www-form-urlencoded”;     这是XDR里唯一允许接入的头信息了
    xdr.send(“name1=value1&name2=value2”);
     
    其他浏览器实现跨域:
    同样使用xhr就可以了,把请求的地址改为绝对地址
    var xhr = createXHR();
    xhr.onreadystatechange = function(){
    if (xhr.readyState == 4){
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
    alert(xhr.responseText);
    } else {
    alert(“Request was unsuccessful: “ + xhr.status);
    }
    }
    };
    xhr.open(“get”, “http://www.somewhere-else.com/page/”, true);
    xhr.send(null);
    有三个限制:
    1、Custom headers cannot be set using setRequestHeader().
    2、Cookies are neither sent nor received.
    3、The getAllResponseHeaders() method always returns an empty string
    为了区分的话请求本地资源用相对地址,外面资源用绝对地址
     
     
    HTTP access control (CORS):跨域资源共享加入新的header,使得服务器可以识别哪些来源可以获取数据,针对会造成副作用的方法(特别是get以外HTTP方法或者搭配某些MIME类型的post方法),该标准规定了需要发送先导请求,以HTTP的option方法从服务器获得支援方法,然后当服务器允许之后,再通用真实的HTTP请求方法来发送真正的数据。服务器可以通知客户端是否要把验证信息(cookie和HTTP验证资料)也一起随请求发出。

     
     
    兼容两者的函数:
    function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    if (“withCredentials” in xhr){    通过检测是否含有 withCredentials可以判断当前xhr对象是否支持跨域请求
    xhr.open(method, url, true);
    } else if (typeof XDomainRequest != “undefined”){
    xhr = new XDomainRequest();
    xhr.open(method, url);
    } else {
    xhr = null;
    }
    return xhr;
    }
     
     
    Preflighted Requests(先导请求)(当使用GET, HEAD, POST以外的方法。而且當用POST方法時,如果請求連帶的資料其Content-Type不為application/x-www-form-urlencoded, multipart/form-data, 或text/plain,例如POST請求連帶的資料是application/xml或text/xml的XML類型資料,那麼先導請求就會先送出。或者請求中有自訂義標頭,例如自定义一個X-PINGOTHER  header。)
    当你尝试定制头部信息,使用get,post之外的请求方式,不同的content类型时,一个 Preflighted请求会发送给 服务器。这种请求使用OPTIONS方法,发送下面的header:
    Origin — Same as in simple requests.
    Access-Control-Request-Method — The method that the request wants to use.
    Access-Control-Request-Headers — (Optional) A comma-separated list of the custom headers being used.

    服务器可以决定是否支持这类请求,通过响应header来反馈:
    Access-Control-Allow-Origin — Same as in simple requests.
    Access-Control-Allow-Methods — A comma-separated list of allowed methods.
    Access-Control-Allow-Headers — A comma-separated list of headers that the server will allow.
    Access-Control-Max-Age — The amount of time in seconds that this prefl ight request should be cached for.
    Access-Control-Allow-Credentials   這個標頭指示了當請求的credentials設定true時,是否要回應請求
    Access-Control-Expose-Headers    這個標頭指示瀏覽器允許存取的標頭白名單
    响应结果会按照 Access-Control-Max-Age的时间缓存起来,只会在第一次请求时才会额外增加一个HTTP请求。
     
    Credentialed Requests(附带验证信息请求)
    跨域请求默认是不提供验证信息的,但是可以通过把 withCredentials设置为true来开启该功能,如果服务器允许就会在相应中返回:
    Access-Control-Allow-Credentials: true
    浏览器就可以获取求响应中的验证信息,如果没有在相应中返回的话,浏览器会拒绝任何响应,不会把响应传给JavaScript处理( responseText is an empty string, status is 0, and onerror() is invoked)
     
    注意:当响应中带了安全信息的时候,服务器必须显示指出请求来源,Access-Control-Allow-Origin不能为*通配符。否则也会被浏览器拒绝
     
    上面两种请求ie10及以下都不支持
  • 相关阅读:
    提高 github.com 项目下载速度
    理解git 中的HEAD指针&branch指针
    Docker Compose 配置文件详解
    Yarn 配置阿里源
    Laravel
    reCAPTCHA打不开的解决方法
    CC2 条理分明-----独立思考
    CC2 条理分明-----AACTP教你谈恋爱
    CC4 表达方式----输赢
    lambda匿名函数透析
  • 原文地址:https://www.cnblogs.com/chuangweili/p/5166332.html
Copyright © 2020-2023  润新知