有個朋友在寫扇貝插件的時候遇到了跨域問題。
因而我對解決跨域問題的方式進行了一番探討。javascript
問題css
API:查詢單詞
URL: https://api.shanbay.com/bdc/search/?word={word}
請求方式: GET
參數: {word}, 必須,要查詢的單詞html
報錯爲前端
XMLHttpRequest cannot load http://localhost/home/saveCandidate. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 404.
這就是典型的跨域問題。java
可是我在瀏覽器裏輸入URL是能夠進行查詢單詞的操做的,有什麼不一樣,即下面兩個問題node
通過Google和本身測試jquery
同源策略:web
同源指的是域名(或IP),協議,端口都相同,不一樣源的客戶端腳本(javascript、ActionScript)在沒明確受權的狀況下,不能讀寫對方的資源。ajax
URL | 解釋 | 是否跨域 |
---|---|---|
http://www.morethink.cn | 原來的URL | |
http://www.image.morethink.cn | 子域名 | 跨域(cookie也沒法訪問) |
http://morethink.cn | 不加www | 跨域 |
https://www.morethink.cn | 更改協議 | 跨域 |
http://www.morethink.cn:8080 | 更改端口號 | 跨域 |
緣由:json
同源政策的目的,是爲了保證用戶信息的安全,防止惡意的網站竊取數據。
設想這樣一種狀況:A網站是一家銀行,用戶登陸之後,又去瀏覽其餘網站。若是其餘網站能夠讀取A網站的Cookie,會發生什麼?
很顯然,若是Cookie包含隱私(好比存款總額),這些信息就會泄漏。更可怕的是,Cookie每每用來保存用戶的登陸狀態,若是用戶沒有退出登陸,其餘網站就能夠冒充用戶,隨心所欲。由於瀏覽器同時還規定,提交表單不受同源政策的限制。
因而可知,"同源政策"是必需的,不然 Cookie 能夠共享,互聯網就毫無安全可言了。
同源策略限制如下幾種行爲:
測試URL爲 http://localhost:80/home/allProductions
能夠直接在瀏覽器console
中執行
var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:80/home/allProductions',true); xhr.send(); xhr.onreadystatechange=function() { if(xhr.readyState == 4) { if(xhr.status == 200) { console.log(JSON.parse(xhr.responseText)); } } }
在任意網站打開控制檯,執行此段代碼能夠模擬跨域請求。
在知乎控制檯打開報錯以下
Mixed Content: The page at 'https://www.zhihu.com/question/26376773' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://localhost/home/allProductions'. This request has been blocked; the content must be served over HTTPS.
由於知乎是https,報錯與普通的http協議不一樣。
再澄清一下跨域問題:
在博客園控制檯打開報錯以下
XMLHttpRequest cannot load http://localhost/home/allProductions. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.cnblogs.com' is therefore not allowed access.
解決方案有不少
這裏主要介紹SpringMVC解決跨域問題的方式。
能夠直接參考Spring MVC 4.1 支持jsonp進行配置你的SpringMVC註解
我雖然請求不了json數據,可是我能夠請求一個Content-Type
爲application/javascript
的JavaScript對象,這樣就能夠避免瀏覽器的同源策略。
就是當服務器接受到名爲jsonp
或者callback
的參數時,返回Content-Type: application/javascript
的結果,從而避免瀏覽器的同源策略檢測。
在控制檯中直接進行測試你的jsonp是否配置成功:
function println(data) { console.log(data); } var url = "http://localhost:80/home/allProductions?&callback=println"; // 建立script標籤,設置其屬性 var script = document.createElement('script'); script.setAttribute('src', url); // 把script標籤加入head,此時調用開始 document.getElementsByTagName('head')[0].appendChild(script);
使用JQuery測試你的jsonp是否配置成功,由於控制檯不能直接加載JQuery,須要本身創建html文件來進行測試:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="http://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script> <script type="text/javascript"> function println(data) { console.log(data); console.log('print'); } function jsonp_test() { $.ajax({ type: "get", url: "http://localhost:80/home/allProductions", dataType: "jsonp", jsonp: "callback",//傳遞給請求處理程序或頁面的,用以得到jsonp回調函數名的參數名(通常默認爲:callback) jsonpCallback: "println", //返回後調用的處理函數 error: function () { //請求出錯的處理 alert("請求出錯"); } }); } </script> </head> <body onload="jsonp_test()"> </body> </html>
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。
它容許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
CORS須要瀏覽器和服務器同時支持。
即CORS與普通請求代碼同樣。
CORS與JSONP相比
@CrossOrigin
註解此註解既可用於方法也可用於類
源碼以下:
@CrossOrigin(origins = "http://www.zhihu.com") @RequestMapping(value = "/allProductions", method = RequestMethod.GET) public Result getAllOldProductions() { }
@CrossOrigin
註解既可註解在方法上,也可註解在類上。
完成配置以後
全部跨域請求均可以訪問
<mvc:cors> <mvc:mapping path="/**" /> </mvc:cors>
更加細粒度的配置:
<mvc:cors> <mvc:mapping path="/api/**" allowed-origins="http://domain1.com, http://domain2.com" allowed-methods="GET, PUT" allowed-headers="header1, header2, header3" exposed-headers="header1, header2" allow-credentials="false" max-age="123" /> <mvc:mapping path="/resources/**" allowed-origins="http://domain1.com" /> </mvc:cors>
WebSocket是一種通訊協議,使用ws://(非加密)和wss://(加密)做爲協議前綴,在2008年誕生,2011年成爲國際標準。全部瀏覽器都已經支持了。
它的最大特色就是,服務器能夠主動向客戶端推送信息,客戶端也能夠主動向服務器發送信息,是真正的雙向平等對話,屬於服務器推送技術的一種。
該協議不實行同源政策,只要服務器支持,就能夠經過它進行跨源通訊。
請求頭信息:(多了個 origin)
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
響應頭:(若是origin在白名單內)
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
HTTP/2只是對HTML、CSS等JS資源的傳輸方式進行了優化,並無提供新的JS API,不能用於實時傳輸消息,也沒法推送指定的信息。
參考文檔: