【問題】
使用allure生成報告,當報告用本地的文件夾直接打開html文件之后,發現頁面資源都加載不出來...只有用
npm run open-allure
才能正常加載出來
頁面某些資源請求失敗,打開瀏覽器F12發現提示:
from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
其實是瀏覽器 同源策略
問題,或者叫 跨域問題
常見於用Chrome調試腳本的時候,需要加載的腳本和location
不同源
【跨域】
瀏覽器從一個域名的網頁去請求另一個域名的資源時,域名、端口、協議任一不同,都是跨域
【為什么會有跨域】
在前后端分離的模式下,前后端的域名是不一致的,此時就會發生跨域訪問問題。在請求的過程中我們要想回去數據一般都是post/get請求,所以..跨域問題出現
跨域問題來源於JavaScript的同源策略,即只有 協議+主機名+端口號(如存在)相同,則允許相互訪問。也就是說JavaScript只能訪問和操作自己域下的資源,不能訪問和操作其他域下的資源。
跨域問題是針對JS和ajax的,html本身沒有跨域問題,比如a標簽、script標簽、甚至form標簽(可以直接跨域發送數據並接收數據)等
跨域的方案
CORS: 服務器設置允許,瀏覽器要能夠識別這個頭
JSONP:
瀏覽器script的src支持跨域訪問,發了一個callback去服務器
服務器接受callback 返回了一個函數的調用攜帶了數據回來
瀏覽器接收到返回值當做js解析,執行代碼
【什么是同源策略】
1、同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。
2、所謂同源是指"協議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
3、同源策略限制以下幾種行為:
(1)Cookie、LocalStorage 和 IndexDB 無法讀取
(2)DOM 和 Js對象無法獲得
(3)AJAX 請求不能發送
瀏覽器采用同源策略,禁止頁面加載或執行與自身來源不同的域的任何腳本。換句話說瀏覽器禁止的是來自不同源的"document"或腳本,對當前"document"讀取或設置某些屬性。
情景:
比如一個惡意網站的頁面通過iframe嵌入了銀行的登錄頁面(二者不同源),如果沒有同源限制,惡意網頁上的javascript腳本就可以在用戶登錄銀行的時候獲取用戶名和密碼。
瀏覽器中有哪些不受同源限制呢?
<script>、<img>、<iframe>、<link>這些包含 src 屬性的標簽可以加載跨域資源。但瀏覽器限制了JavaScript的權限使其不能讀、寫加載的內容。
【解決方案】
常見的解決方案分為三種,Nginx代理(前端實現),JSONP(前端實現),后台設置(后端實現)。
1.Nginx代理(前端實現):
案例說明:前端項目部署在8081端口,后端8081端口。
nginx監聽8081端口,將前端從nginx監聽的端口8081請求過來的請求,代理轉發到8080端口(8080為后端接口)
1、JSONP
前端實現:
$.ajax({ url: 'http://www.domain2.com:8080/login', type: 'get', dataType: 'jsonp', // 請求方式為jsonp jsonpCallback: "onBack", // 自定義回調函數名 data: {} });
后端實現(SpringBoot)
@ControllerAdvice(basePackages = "com.zkn.learnspringboot.web.controller") public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{ public JsonpAdvice() { super("callback","jsonp"); } }
(1)前端發起請求時候,會加一個參數表示回調的函數 比如 callback=callback124 (callback 參數名也是可以自定義的,和后端協商好就行)
后端返回的數據 callback124({“uid”:1})
(2)參考:前端常見跨域解決方案(全) https://segmentfault.com/a/1190000011145364
(3)JSONP的缺點
JSONP只支持 GET 請求。
(4)原理
JSONP 是通過動態添加<script>標簽來調用服務器的腳本(<script>含有src屬性,src屬性沒有跨域限制);而 Ajax 是通過 XHR(XmlHttpRequest) 對象。
2、跨域技術-CORS (CrossOrigin Resources Sharing,跨源資源共享)
CORS是什么?
CORS,是 HTML5 的一項特性,它定義了一種瀏覽器和服務器交互的方式來確定是否允許跨域請求。
相對於 JSONP 這種解決方案來說,使用CORS,不需要要求服務器以指定格式返回數據(包裝成JS腳本的格式:callback_func({ data }););CORS,只需要在服務器端做一些通用設置。
前端實現:
$.ajax({ type: "post", url: 'http://192.168.45.152:8081/conference/user/bind', async: false, // 使用同步方式 // 1 需要使用JSON.stringify 否則格式為 a=2&b=3&now=14... // 2 需要強制類型轉換,否則格式為 {"a":"2","b":"3"} data: JSON.stringify({ a: 1, b: '2', now: new Date().getTime() // 注意不要在此行增加逗號 }), headers: { 'Authentication':'xxxxxx' }, contentType: "text/plain", dataType: "json", success: function(data) { console.log(data) } // 注意不要在此行增加逗號 });
后端實現(SpringBoot):
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { //設置允許跨域的路徑 registry.addMapping("/**") //設置允許跨域請求的域名 .allowedOrigins("*") //是否允許證書 不再默認開啟 .allowCredentials(true) //設置允許的方法 .allowedMethods("GET", "POST") //跨域允許時間 .maxAge(3600); } }
CORS與JSONP的使用目的相同,但是比JSONP更強大。
JSONP只支持GET請求,CORS支持所有類型的HTTP請求。JSONP的優勢在於支持老式瀏覽器,以及可以向不支持CORS的網站請求數據。
【跨域會話保持】
對於前端來說,seesion字段是存在cookie中的。在跨域過程中,Cookie是默認不發送的。就算后端返回set-Cookie字段,前端也不會保存Cookie,更不會在下一次訪問的時候發送到后端了。
因此只要前端可以把cookie發送到后端,后端就可以根據cookie拿到seeion字段進行會話驗證。
進過重新對CORS的學習,只要通過3步,就可以讓會話保持。
1、在ajax中設置,withCredentials: true。
默認情況下,跨源請求不提供憑據(cookie、HTTP認證及客戶端SSL證明等)。通過將withCredentials屬性設置為true,可以指定某個請求應該發送憑據。
$.ajax({ url: a_cross_domain_url, xhrFields: { withCredentials: true } });
第二第三步,就是上面的服務端CORS的跨域技術
服務端的 Access-Control-Allow-Credentials: true,代表服務器接受Cookie和HTTP認證信息。
參考資料:
(1)前后端分離-跨域會話如何保持?
https://www.jianshu.com/p/26f877d2b315?tdsourcetag=s_pcqq_aiomsg
(2)Session與Token認證機制 前后端分離下如何登錄
https://www.cnblogs.com/eret9616/p/9661314.html?tdsourcetag=s_pcqq_aiomsg
(3)理解Cookie和Session機制
https://www.cnblogs.com/andy-zhou/p/5360107.html
轉: https://blog.csdn.net/kevinxxw/article/details/90547184