SpringBoot中通過CORS解決跨域問題
同源策略
很多人對跨域有一種誤解,以為這是前端的事,和後端沒關係,其實不是這樣的,說到跨域,就不得不說說瀏覽器的同源策略。
同源策略是由Netscape
提出的一個著名的安全策略,它是瀏覽器最核心也最基本的安全功能,現在所有支援JavaScript的瀏覽器都會使用這個策略。所謂同源是指協議、域名以及埠要相同。同源策略是基於安全方面的考慮提出來的,這個策略本身沒問題,但是我們在實際開發中,由於各種原因又經常有跨域的需求,傳統的跨域方案是JSONP
,JSONP
雖然能解決跨域但是有一個很大的侷限性,那就是隻支援GET
請求,不支援其他型別的請求,而今天我們說的CORS
(跨域源資源共享)(CORS,Cross-origin resource sharing)是一個W3C標準,它是一份瀏覽器技術的規範,提供了Web服務從不同網域傳來沙盒指令碼的方法,以避開瀏覽器的同源策略,這是JSONP模式的現代版。
在Spring框架中,對於CORS
也提供了相應的解決方案,今天我們就來看看SpringBoot中如何實現CORS。
實踐
首先建立兩個普通的SpringBoot專案,這個就不用我多說,第一個命名為provider
提供服務,第二個命名為consumer
消費服務,第一個配置埠為8080
,第二個配置配置為8081
,然後在provider上提供兩個hello介面,一個get
,一個post
,如下:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
@PostMapping("/hello")
public String hello2() {
return "post hello";
}
}
在consumer
的resources/static
目錄下建立一個html檔案,傳送一個簡單的ajax
請求,如下:
<div id="app"></div>
<input type="button" onclick="btnClick()" value="get_button">
<input type="button" onclick="btnClick2()" value="post_button">
<script>
function btnClick() {
$.get('http://localhost:8080/hello', function (msg) {
$("#app").html(msg);
});
}
function btnClick2() {
$.post('http://localhost:8080/hello', function (msg) {
$("#app").html(msg);
});
}
</script>
然後分別啟動兩個專案,傳送請求按鈕,觀察瀏覽器控制檯如下:
可以看到,由於同源策略的限制,請求無法傳送成功
使用CORS可以在前端程式碼不做任何修改的情況下,實現跨域,那麼接下來看看在provider
中如何配置。首先可以通過@CrossOrigin註解
配置某一個方法接受某一個域的請求,如下:
@RestController
public class HelloController {
@CrossOrigin(value = "http://localhost:8081")
@GetMapping("/hello")
public String hello() {
return "hello";
}
@CrossOrigin(value = "http://localhost:8081")
@PostMapping("/hello")
public String hello2() {
return "post hello";
}
}
這個註解表示這兩個介面接受來自http://localhost:8081
地址的請求,配置完成後,重啟provider,再次傳送請求,瀏覽器控制檯就不會報錯了,consumer也能拿到資料了。
此時觀察瀏覽器請求網路控制檯,可以看到響應頭中多瞭如下資訊:
這個表示服務端願意接收來自http://localhost:8081
的請求,拿到這個資訊後,瀏覽器就不會再去限制本次請求的跨域了。
provider
上,每一個方法上都去加註解未免太麻煩了,在Spring Boot中,還可以通過全域性配置一次性解決這個問題,全域性配置只需要在配置類中重寫addCorsMappings
方法即可,如下:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8081")
.allowedMethods("*")
.allowedHeaders("*");
}
}
/**
表示本應用的所有方法都會去處理跨域請求,allowedMethods
表示允許通過的請求數,allowedHeaders
則表示允許的請求頭。經過這樣的配置之後,就不必在每個方法上單獨配置跨域了。
存在的問題
瞭解了整個CORS的工作過程之後,我們通過Ajax傳送跨域請求,雖然使用者體驗提高了,但是也有潛在的威脅存在,常見的就是CSRF(Cross-site request forgery)跨站請求偽造。跨站請求偽造也被稱為one-click attack 或者 session riding,通常縮寫為CSRF或者XSRF,是一種挾制使用者在當前已登入的Web應用程式上執行非本意的操作的攻擊方法,舉個例子:
假如一家銀行用以執行轉賬操作的URL地址如下:http://icbc.com/aa?bb=cc,
那麼,一個惡意攻擊者可以在另一個網站上放置如下程式碼:<img src="http://icbc.com/aa?bb=cc">,
如果使用者訪問了惡意站點,而她之前剛訪問過銀行不久,登入資訊尚未過期,那麼她就會遭受損失。
基於此,瀏覽器在實際操作中,會對請求進行分類,分為簡單請求,預先請求,帶憑證的請求等,預先請求會首先傳送一個options
探測請求,和瀏覽器進行協商是否接受請求。預設情況下跨域請求是不需要憑證的,但是服務端可以配置要求客戶端提供憑證,這樣就可以有效避免csrf攻擊
。
相關文章
- cors解決跨域問題CORS跨域
- 深入跨域問題(2) - 利用 CORS 解決跨域跨域CORS
- Nginx解決前端跨域問題 CORS跨域配置Nginx前端跨域CORS
- 跨域問題,解決方案 – CORS方案跨域CORS
- 解決跨域問題 barryvdh/Laravel-cors跨域LaravelCORS
- has been blocked by CORS policy跨域問題解決BloCCORS跨域
- SpringBoot跨域問題解決方案Spring Boot跨域
- 解決CORS跨域不能傳遞cookies的問題CORS跨域Cookie
- CORS跨域問題梳理CORS跨域
- SpringBoot解決前後端跨域問題Spring Boot後端跨域
- springboot配置CORS允許跨域訪問Spring BootCORS跨域
- Spring Boot 通過CORS實現跨域Spring BootCORS跨域
- 解決跨域問題跨域
- 搞懂:前端跨域問題JS解決跨域問題VUE代理解決跨域問題原理前端跨域JSVue
- springboot 跨域問題Spring Boot跨域
- 【JavaScript】通過封裝自己的JSONP解決瀏覽器的跨域問題(Ajax跨域)JavaScript封裝JSON瀏覽器跨域
- 跨域CORS圖片上傳問題跨域CORS
- Cors跨域問題中文官方文件CORS跨域
- Spring boot 和Vue開發中CORS跨域問題Spring BootVueCORS跨域
- WebSocket跨域問題解決Web跨域
- Java解決跨域問題Java跨域
- Flask解決跨域問題Flask跨域
- CROS 解決跨域問題ROS跨域
- SignalR跨域問題解決SignalR跨域
- Luffy - 解決跨域問題跨域
- Vue中跨域問題解決方案1Vue跨域
- 深入跨域問題(1) - 初識 CORS 跨域資源共享跨域CORS
- 深入跨域問題(3) – 利用 JSONP 解決跨域跨域JSON
- 深入跨域問題(3) - 利用 JSONP 解決跨域跨域JSON
- 跨域問題(CORS / Access-Control-Allow-Origin)跨域CORS
- 跨域問題及解決方案跨域
- 輕鬆解決跨域問題跨域
- thinkphp 5 跨域問題解決PHP跨域
- JAVA | Java 解決跨域問題Java跨域
- 跨域問題解決辦法跨域
- 學習AJAX必知必會(5)~同源策略、解決跨域問題(JSONP、CORS)跨域JSONCORS
- 解決JS跨域訪問的問題JS跨域
- 搞定所有的跨域請求問題: jsonp & CORS跨域JSONCORS