什麼是跨域?瀏覽器從一個功能變數名稱的網頁去請求另一個功能變數名稱的資源時,功能變數名稱、埠、協議任一不同,都是跨域 。 跨域資源訪問是經常會遇到的場景,當一個資源從與該資源本身所在的伺服器不同的域或埠請求一個資源時,資源便會發起一個跨域 HTTP 請求。出於安全考慮,瀏覽器會限制從腳本內發起的跨域HTTP請求。 ...
什麼是跨域?瀏覽器從一個功能變數名稱的網頁去請求另一個功能變數名稱的資源時,功能變數名稱、埠、協議任一不同,都是跨域 。 跨域資源訪問是經常會遇到的場景,當一個資源從與該資源本身所在的伺服器不同的域或埠請求一個資源時,資源便會發起一個跨域 HTTP 請求。出於安全考慮,瀏覽器會限制從腳本內發起的跨域HTTP請求。
vCORS方式實現跨域
跨域的方式有很多種, 今天主要介紹CORS(網路通信技術),全稱Cross-Origin Resource Sharing ,是一種允許當前域(domain)的資源(比如html/js/web service)被其他域(domain)的腳本請求訪問的機制,通常由於同域安全策略(the same-origin security policy)瀏覽器會禁止這種跨域請求。
v服務端配置
由於CORS方式實現跨域需要服務端配合設置Header,在springboot中只需要添加以下配置即可,或者在需要支持跨域的方法中直接對response設置header,以下三種方式效果相同。
第一種:
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { /** * 重寫addCorsMappings方法實現跨域的設置 * 當然跨域還可以通過在Controller或方法上添加‘@CrossOrigin("http://domain2.com")’的註解實現,不過下麵這種方便統一管理 * 參考:https://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html */ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://a.test.com") //允許的origin .allowedMethods("GET", "POST", "DELETE") //允許的方法 .allowCredentials(true) //是否允許攜帶cookie .maxAge(3600); } //全局跨域,Enabling CORS for the whole application is as simple as: /*@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**"); }*/ }
第二種:
@RequestMapping public Object index(HttpServletRequest request, HttpServletResponse response, @CookieValue(value = "sid", required = false) String sid) { response.setHeader("Access-Control-Allow-Origin","http://a.test.com"); //允許跨域的Origin設置 response.setHeader("Access-Control-Allow-Credentials","true"); //允許攜帶cookie logger.info("cookie sid = " + sid); return restTemplateService.someRestCall(); }
第三種:
@RequestMapping @CrossOrigin(origins = "http://a.test.com", allowCredentials = "true") public Object index(HttpServletRequest request, @CookieValue(value = "sid", required = false) String sid) { logger.info("cookie sid = " + sid); return restTemplateService.someRestCall(); }
v前端調用方式
1. 原生ajax調用示例:
var xhr = new XMLHttpRequest(); xhr.open("POST", "http://b.test.com/api/rest", true); xhr.withCredentials = true; //支持跨域發送cookies xhr.send();
2. jQuery調用示例:
$.ajax({ url: 'http://b.test.com/api/rest', dataType: 'json', type : 'POST', xhrFields: { withCredentials: true //是否攜帶cookie }, crossDomain: true, contentType: "application/json", success: (res) => { console.log(res); } });
3. fetch方式
fetch('http://b.test.com/api/rest', {credentials: 'include'} //註意這裡的設置,支持跨域發送cookies ).then(function(res) { if (res.ok) { res.json().then(function(data) { console.log(data.value); }); } else { console.log("Looks like the response wasn't perfect, got status", res.status); } }, function(e) { console.log("Fetch failed!", e); });
v註意事項
值得註意的一點是:伺服器端 Access-Control-Allow-Credentials = true時,參數Access-Control-Allow-Origin 的值不能為 '*',必須為具體的origin。
另外還需要註意:試了一下,cookie的域必須是兩個子域的頂級域,才能實現跨域傳輸。即如果網站A是:a.test.cn,網站B是:b.test.com,那麼無論如何都不能實現A攜帶會話cookie發送跨域請求到網站B上。
其他參考資料:
- SpringBoot配置Cors解決跨域請求問題 https://www.cnblogs.com/yuansc/p/9076604.html
- enable cross-origin resource sharing https://enable-cors.org/
- Understanding CORS https://spring.io/understanding/CORS
作 者:請叫我頭頭哥
出 處:http://www.cnblogs.com/toutou/
關於作者:專註於基礎平臺的項目開發。如有問題或建議,請多多賜教!
版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
特此聲明:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角【推薦】一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!