SpringBoot(十三)CORS方式實現跨域
什麼是跨域?瀏覽器從一個域名的網頁去請求另一個域名的資源時,域名、埠、協議任一不同,都是跨域 。 跨域資源訪問是經常會遇到的場景,當一個資源從與該資源本身所在的伺服器不同的域或埠請求一個資源時,資源便會發起一個跨域 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/
關於作者:專注於基礎平臺的專案開發。如有問題或建議,請多多賜教!
版權宣告:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。
特此宣告:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我
聲援博主:如果您覺得文章對您有幫助,可以點選文章右下角【推薦】一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!