跨域請求CORS

預(yù)備知識:

  1. 只有瀏覽器才會有跨域請求限制,也就是如果是服務(wù)器之間直接發(fā)起http請求不會存在該限制。
  2. CORS是在不滿足同源策略的情況下,才有可能引起跨域請求限制。
  3. 同源策略校驗包括protocol + host/domain + port(80/443會省略),只有三者完全相同是,才滿足同源策略。
  4. <script><img><iframe><link><video><audio>帶有src屬性,瀏覽器允許跨域請求
  5. 表單提交、重定向允許跨域?qū)懖僮鳎ù藭r可能引起CSRF,可以通過埋token的方式避免)
  6. 瀏覽器不支持跨站點訪問Cookie、LocalStorage、IndexDB
  7. 瀏覽器不支持跨站點訪問DOM
  8. 瀏覽器不支持跨站點的AJAX請求,在不進行跨域請求配置的情況下。

跨域請求的解決方案:

  • 簡單請求

    • 請求method只能是GET/POST/HEAD
    • 僅能使用CORS安全的Header: Accept、Accept-Language、Content-Language、Content-Type
    • Content-Tytpe只能是如下的一種:text/plain、multipart/form-data、applicaton/x-www-form-urlencoded
    • 請求中必須攜帶Origin頭部,服務(wù)端通過響應(yīng)Access-Control-Allow-Origin頭部來只是瀏覽器該如何處理該請求(如果Access-Control-Allow-Origin為Origin的值或者為*時,瀏覽器才允許渲染請求結(jié)果)
  • 復(fù)雜請求

請求示例:

  1. 創(chuàng)建html文件,內(nèi)部含有Ajax請求(http://127.0.0.1:8081和http://127.0.0.1:8082不滿足同源策略)
<html>
<body>
    <p>跨域請求測試</p>
    <p id="resp"></p>
    <script>
        var invocation = new XMLHttpRequest();
        var url = "http://127.0.0.1:8082";

        function handler() {
            if (invocation.readyState == 4) {
                if (invocation.status==200) {
                    console.log(invocation.responseText);
                    document.getElementById('resp').innerHTML=invocation.responseText;
                }
            }
        }

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

        callOtherDomain();
    </script>
</body>
</html>%
```html

2. 配置nginx server
server {
    listen      8081;
    server_name localhost;
    charset     utf-8;

    location / {
        # 這個地方需要修改成你上面保存的cors.html的目錄
        root /path-to-directory;
        index cors.html cors.htm;
    }
}

server {
    listen      8082;
    server_name localhost;
    charset     utf-8;

    location / {
        return 200 'hello world';
    }
}

保存,執(zhí)行nginx -s reload

  1. 打開瀏覽器,訪問http://127.0.0.1:8081。你將會發(fā)現(xiàn)http://127.0.0.1:8082的Ajax請求失敗了,瀏覽器提示CORS error(MissingAllowOriginHeader) 。
    但是通過抓包可以看到,nginx其實將相應(yīng)('hello world')返回給瀏覽器了,但是由于不滿足CORS policy,相應(yīng)被瀏覽器隱藏了。抓包截圖:


    image.png

3.1 修改8082站點的配置,以允許來自8081的跨站請求

    server {
        listen      8082;
        server_name localhost;
        charset     utf-8;

        location / {
            add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081';
            return 200 'hello world';
        }
    }

再次刷新瀏覽器,可以發(fā)現(xiàn)請求正常返回了
因為Response header中返回了Access-Control-Allow-Origin: http://127.0.0.1:8081

4. 更多的跨域請求響應(yīng)Header

image.png

5. 常見錯誤

5.1 MultipleAllowOriginValues

Access to XMLHttpRequest at 'http://127.0.0.1:8082/' from origin 'http://127.0.0.1:8081' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values 'http://127.0.0.1:8081, http://127.0.0.1:8083', but only one is allowed.

原因:response header中返回了多個AccessControlAllowOrigin值(可以是相同的,也可以是不同的)。例如如下的服務(wù)端返回:

    server {
        listen      8082;
        server_name localhost;
        charset     utf-8;

        location / {
            add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081';
            add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081';
            return 200 'hello world';
        }
    }

Access-Control-Allow-Origin只能返回一個源

add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081';
add_header Access-Control-Allow-Origin 'http://127.0.0.1:8083';
這種不同的源也是不行的,即使相同的源也是不行的。
add_header Access-Control-Allow-Origin 'http://127.0.0.1:8081,http://127.0.0.1:8083';
這種也是不行的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容