什麼是跨域?瀏覽器從一個域名的網頁去請求另外一個域名的資源時,域名、端口、協議任一不一樣,都是跨域 。 跨域資源訪問是常常會遇到的場景,當一個資源從與該資源自己所在的服務器不一樣的域或端口請求一個資源時,資源便會發起一個跨域 HTTP 請求。出於安全考慮,瀏覽器會限制從腳本內發起的跨域HTTP請求。html
跨域的方式有不少種, 今天主要介紹CORS(網絡通訊技術),全稱Cross-Origin Resource Sharing ,是一種容許當前域(domain)的資源(好比html/js/web service)被其餘域(domain)的腳本請求訪問的機制,一般因爲同域安全策略(the same-origin security policy)瀏覽器會禁止這種跨域請求。前端
因爲CORS方式實現跨域須要服務端配合設置Header,在springboot中只須要添加如下配置便可,或者在須要支持跨域的方法中直接對response設置header,如下三種方式效果相同。java
第一種:git
@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("/**"); }*/ }
第二種:github
@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(); }
第三種:web
@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(); }
1. 原生ajax調用示例:ajax
var xhr = new XMLHttpRequest(); xhr.open("POST", "http://b.test.com/api/rest", true); xhr.withCredentials = true; //支持跨域發送cookies xhr.send();
2. jQuery調用示例:spring
$.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方式json
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); });
值得注意的一點是:服務器端 Access-Control-Allow-Credentials = true時,參數Access-Control-Allow-Origin 的值不能爲 '*',必須爲具體的origin。api
另外還須要注意:試了一下,cookie的域必須是兩個子域的頂級域,才能實現跨域傳輸。即若是網站A是:a.test.cn,網站B是:b.test.com,那麼不管如何都不能實現A攜帶會話cookie發送跨域請求到網站B上。
其餘參考資料:
https://github.com/toutouge/javademosecond/tree/master/hellospringboot
做 者:請叫我頭頭哥
出 處:http://www.cnblogs.com/toutou/
關於做者:專一於基礎平臺的項目開發。若有問題或建議,請多多賜教!
版權聲明:本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。
特此聲明:全部評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我
聲援博主:若是您以爲文章對您有幫助,能夠點擊文章右下角【推薦】一下。您的鼓勵是做者堅持原創和持續寫做的最大動力!