<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 1. 從跨域到 CORS #### 1. 介紹 跨域,可能很多前端開發者都會遇到過,也可能知道有jsonp,iframe之類的跨域方法。不過要說這些方法之前,先得來說說什么叫跨域,為什么要跨域。 所謂跨域,顧名思義,跨到了另外的域,域不僅僅指的是不同的域名網站,可能同一個域名不同的端口號也算不同的域。瀏覽器是有規則的,只要協議、域名、端口有任何一個不同,都被當作是不同的域。協議指的是http,或者https等。 下面給出一個列表,指出不同域的情況: ![](https://box.kancloud.cn/ea0f3b97e79986064c3afaffdbe6e1b4_532x203.png) 這個叫瀏覽器的同源策略(same-origin policy),為什么要這樣規定呢,原因之一就是為了安全。 假如你在A網站,用一段js腳本就能訪問B網站,B網站憑什么讓你訪問,為什么瀏覽器能讓你隨便訪問別的網站呢,說不定B網站存在著各種危險,比如盜取你的密碼,跨域攻擊(CSRF)等,一切都不太合理。 但也是有例外的情況,有些情況是要訪問到別的網站的,比如加載一張圖片,這張圖片可能在別的網站,還有加載一個js文件,也是有可能在別的網站的,還有嵌入一個frame元素,也可以訪問到別的網站的內容。 所以跨域正是利用了上面幾點,比如jsonp就是利用的加載js文件的功能,比如在`<script src="..."></script>`中的src指定為目標網站的js,同理,還有跨域攻擊也可以利用`<image src="..." />`的功能。還有iframe更能直接加載別的網站的內容到自己的網站里來。 這前面幾種可以說是技巧,說句不好聽的就是瀏覽器的漏洞,瀏覽器并未從正面上支持跨域,而且上面的幾種跨域方法也是有各種局限,比如jsonp的方法,只能用GET方法,iframe方法是能直接加載內容到網站上,但是本網站和iframe的數據交互也是一個頭疼的地方。 畢竟從iframe加載內容到本站后,是存在著數據交互的,可以用`document.domain`,`window.name`,不過這些方法都能用,且有效,不過總不盡完美,存在著各種各樣的局限。 然而HTML5引進了一個叫window.postMessage方法來跨域傳送數據,這個倒是不錯,不過也是利用了iframe。 除此之外,還有flash,服務器代理等跨域方法,但是本章要介紹的是瀏覽器或服務器的跨域方法,它的名字叫CORS。 #### 2. CORS CORS全稱是Cross-Origin Resource Sharing,跨域資源共享,這是瀏覽器的標準,也算是協議,基本上現代瀏覽器都支持,除了奇葩瀏覽器,例如IE8、IE9,只支持部分特性。 使用它,需要服務器端和客戶端兩方面的準備,服務器端我們選擇nginx作為測試,客戶端只是js罷了。 nginx服務監聽在localhost的8080端口,而現在有一個網站運行localhost的3000端口,需要跨域到nginx那臺服務器。 現在開始測試之旅,要在瀏覽器模擬跨域請求,只需三行js代碼。 ``` var xhttp = new XMLHttpRequest(); xhttp.open("GET", "http://localhost:8080", true); xhttp.send(); ``` 我使用的瀏覽器是chrome,打開它的開發者工具,在`console`里運行上面的代碼,效果如下: ![](https://box.kancloud.cn/02ac0d9622f5c2284a3371499635c5aa_1300x576.png) 上面的報錯已經提示得很明顯了,主要是下面這句話: ``` XMLHttpRequest cannot load http://localhost:8080/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. VM162:4 XHR failed loading: GET "http://localhost:8080/". ``` 錯誤中說`Access-Control-Allow-Origin`這個頭信息不存在于被請求的服務器中,來源域`http://localhost:3000`是不允許訪問該服務器的。 `XMLHttpRequest`這個可能很多開發者都明白,那是ajax請求利用的對象,利用它能發起ajax請求,但它的功能不僅僅是發起ajax請求,還能用于跨域,還有設置時限,FormData對象管理表單數據,文件上傳等功能,具體可以自行搜索相關的資料,在這里,它能發起跨域請求就可以了。 我們來看看這個請求相關的信息。 ![](https://box.kancloud.cn/3aacc1964e57cea61bd1c87ca8ae3c86_1329x507.png) 具體的頭信息如下: ``` Request Headers Accept:*/* Accept-Encoding:gzip, deflate, sdch Accept-Language:en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4 Connection:keep-alive Host:localhost:8080 Origin:http://localhost:3000 Referer:http://localhost:3000/ User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36 ``` 最重要的是`Origin:http://localhost:3000`這一行,它標明的是來源的域,這是請求頭信息,會傳給服務器。 我們來看下服務器。 ![](https://box.kancloud.cn/02bbcc8a9a7c9f7883ec91ac974d2a4e_744x257.png) 可見,服務器還是正常響應200狀態的。也就是說,服務器端該怎么應答就怎么應答,只是被瀏覽器給阻止了。 瀏覽器是如何阻止的呢。主要是看響應頭部的信息。 ``` Response Headers Accept-Ranges:bytes Connection:keep-alive Content-Length:612 Content-Type:text/html Date:Mon, 01 Feb 2016 07:17:54 GMT ETag:"56988bc6-264" Last-Modified:Fri, 15 Jan 2016 06:03:50 GMT Server:nginx/1.8.0 ``` 它沒有發現有發現`Origin:http://localhost:3000`這個來源域名是被服務器所允許的。 我們在服務器端設置一下,讓`Origin:http://localhost:3000`這個來源域被允許訪問。 ``` location / { add_header 'Access-Control-Allow-Origin' '*'; } ``` ``add_header 'Access-Control-Allow-Origin' '*'`表示允許任何來源域訪問nginx這臺服務器。 用`sudo nginx -s reload`重新加載服務器配置。 再來看下效果。 ![](https://box.kancloud.cn/8a4d9589e6d4da3f57a3e32c6af74bee_646x197.png) 果然成功了,不再提示錯誤。 來看下響應的信息。 ``` Response Headers Accept-Ranges:bytes Access-Control-Allow-Origin:* Connection:keep-alive Content-Length:612 Content-Type:text/html Date:Mon, 01 Feb 2016 07:25:25 GMT ETag:"56988bc6-264" Last-Modified:Fri, 15 Jan 2016 06:03:50 GMT Server:nginx/1.8.0 ``` 響應信息中多了這一行`Access-Control-Allow-Origin:*`。 原來,瀏覽器在用`XMLHttpRequest`發起跨域請求的時候,它在請求頭帶了`Origin`這個項,而服務器,在響應頭信息中是有響應`Access-Control-Allow-Origin`這項的,兩者比較一下,如果匹配,則請求成功,不匹配就不成功,不過,服務器那邊還是照常執行。 **在測試的時候需要注意的事,有可能會發現改了nginx的配置,瀏覽器發出的跨域請求卻沒生效,這可能是因為瀏覽器cache的原因,只要清除瀏覽器的cache,再重新發起請求就好了。** 下一節[CORS進階之Preflight請求(二)](http://www.rails365.net/articles/cors-jin-jie-zhi-preflight-qing-qiu-er)會介紹CORS更高階的內容,比如`Preflight請求`,`Access-Control-Allow-Methods`,`Access-Control-Allow-Headers`等。 完結。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看