跨域請(qǐng)求CORS

預(yù)備知識(shí):

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

跨域請(qǐng)求的解決方案:

  • 簡(jiǎn)單請(qǐng)求

    • 請(qǐng)求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
    • 請(qǐng)求中必須攜帶Origin頭部,服務(wù)端通過(guò)響應(yīng)Access-Control-Allow-Origin頭部來(lái)只是瀏覽器該如何處理該請(qǐng)求(如果Access-Control-Allow-Origin為Origin的值或者為*時(shí),瀏覽器才允許渲染請(qǐng)求結(jié)果)
  • 復(fù)雜請(qǐng)求

請(qǐng)求示例:

  1. 創(chuàng)建html文件,內(nèi)部含有Ajax請(qǐng)求(http://127.0.0.1:8081和http://127.0.0.1:8082不滿足同源策略)
<html>
<body>
    <p>跨域請(qǐng)求測(cè)試</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 / {
        # 這個(gè)地方需要修改成你上面保存的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. 打開瀏覽器,訪問(wèn)http://127.0.0.1:8081。你將會(huì)發(fā)現(xiàn)http://127.0.0.1:8082的Ajax請(qǐng)求失敗了,瀏覽器提示CORS error(MissingAllowOriginHeader) 。
    但是通過(guò)抓包可以看到,nginx其實(shí)將相應(yīng)('hello world')返回給瀏覽器了,但是由于不滿足CORS policy,相應(yīng)被瀏覽器隱藏了。抓包截圖:


    image.png

3.1 修改8082站點(diǎn)的配置,以允許來(lái)自8081的跨站請(qǐng)求

    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)請(qǐng)求正常返回了
因?yàn)镽esponse header中返回了Access-Control-Allow-Origin: http://127.0.0.1:8081

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

image.png

5. 常見錯(cuò)誤

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中返回了多個(gè)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只能返回一個(gè)源

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)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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