Spring Boot 中三種跨域場景總結

      網友投稿 934 2025-04-02

      文章目錄


      1.什么是跨域

      2.解決方案

      2.1 存在的問題

      3.SpringSecurity

      3.1 方式一

      3.2 方式二

      4.OAuth2

      5.小結

      這次我把 Spring Boot 中的跨域問題分為了三個場景:

      普通跨域

      Spring Security 跨域

      OAuth2 跨域

      分為三種并非多此一舉,主要是因為這三種場景的配置都不太一樣,而這三種場景又都是非常常見的場景,所以這里和大家再來專門分享下。

      1.什么是跨域

      很多人對跨域有一種誤解,以為這是前端的事,和后端沒關系,其實不是這樣的,說到跨域,就不得不說說瀏覽器的同源策略

      同源策略是由 Netscape 提出的一個著名的安全策略,它是瀏覽器最核心也最基本的安全功能,現在所有支持 JavaScript 的瀏覽器都會使用這個策略。所謂同源是指協議、域名以及端口要相同。

      同源策略是基于安全方面的考慮提出來的,這個策略本身沒問題,但是我們在實際開發中,由于各種原因又經常有跨域的需求,傳統的跨域方案是 JSONP,JSONP 雖然能解決跨域但是有一個很大的局限性,那就是只支持 GET 請求,不支持其他類型的請求,在 RESTful 時代這幾乎就沒什么用。

      而今天我們說的 CORS(跨域源資源共享)(CORS,Cross-origin resource sharing)是一個 W3C 標準,它是一份瀏覽器技術的規范,提供了 Web 服務從不同網域傳來沙盒腳本的方法,以避開瀏覽器的同源策略,這是 JSONP 模式的現代版。

      在 Spring 框架中,對于 CORS 也提供了相應的解決方案,在 Spring Boot 中,這一方案得倒了簡化,無論是單純的跨域,還是結合 Spring Security 之后的跨域,都變得非常容易了。

      2.解決方案

      首先創建兩個普通的 Spring Boot 項目,這個就不用我多說,第一個命名為 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"; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      在 consumer 的 resources/static 目錄下創建一個 html 文件,發送一個簡單的 ajax 請求,如下:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      然后分別啟動兩個項目,發送請求按鈕,觀察瀏覽器控制臺如下:

      Access to XMLHttpRequest at 'http://localhost:8080/hello' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

      1

      可以看到,由于同源策略的限制,請求無法發送成功。

      使用 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"; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      這個注解表示這兩個接口接受來自 http://localhost:8081 地址的請求,配置完成后,重啟 provider ,再次發送請求,瀏覽器控制臺就不會報錯了,consumer 也能拿到數據了。

      此時觀察瀏覽器請求網絡控制臺,可以看到響應頭中多了如下信息:

      這個表示服務端愿意接收來自 http://localhost:8081 的請求,拿到這個信息后,瀏覽器就不會再去限制本次請求的跨域了。

      provider 上,每一個方法上都去加注解未免太麻煩了,有的小伙伴想到可以講注解直接加在 Controller 上,不過每個 Controller 都要加還是麻煩,在 Spring Boot 中,還可以通過全局配置一次性解決這個問題,全局配置只需要在 SpringMVC 的配置類中重寫 addCorsMappings 方法即可,如下:

      @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:8081") .allowedMethods("*") .allowedHeaders("*"); } }

      1

      2

      3

      Spring Boot 中三種跨域場景總結

      4

      5

      6

      7

      8

      9

      10

      /** 表示本應用的所有方法都會去處理跨域請求,allowedMethods 表示允許通過的請求數,allowedHeaders 則表示允許的請求頭。經過這樣的配置之后,就不必在每個方法上單獨配置跨域了。

      2.1 存在的問題

      了解了整個 CORS 的工作過程之后,我們通過 Ajax 發送跨域請求,雖然用戶體驗提高了,但是也有潛在的威脅存在,常見的就是 CSRF(Cross-site request forgery)跨站請求偽造。跨站請求偽造也被稱為 one-click attack 或者 session riding,通常縮寫為 CSRF 或者 XSRF,是一種挾制用戶在當前已登錄的 Web 應用程序上執行非本意的操作的攻擊方法。

      關于 CSRF 攻擊的具體介紹和防御辦法,大家可以參考松哥之前的文章,這里就不重復介紹了:

      松哥手把手教你在 SpringBoot 中防御 CSRF 攻擊!so easy!

      要學就學透徹!Spring Security 中 CSRF 防御源碼解析

      3.SpringSecurity

      如果使用了 Spring Security,上面的跨域配置會失效,因為請求被 Spring Security 攔截了。

      當引入了 Spring Security 的時候,我們有兩種辦法開啟 Spring Security 對跨域的支持。

      3.1 方式一

      方式一就是在上一小節的基礎上,添加 Spring Security 對于 CORS 的支持,只需要添加如下配置即可:

      @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .permitAll() .and() .httpBasic() .and() .cors() .and() .csrf() .disable(); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      一個 .cors 就開啟了 Spring Security 對 CORS 的支持。

      3.2 方式二

      方式二則是去除第二小節的跨域配置,直接在 Spring Security 中做全局配置,如下:

      @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .permitAll() .and() .httpBasic() .and() .cors() .configurationSource(corsConfigurationSource()) .and() .csrf() .disable(); } @Bean CorsConfigurationSource corsConfigurationSource() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowCredentials(true); configuration.setAllowedOrigins(Arrays.asList("*")); configuration.setAllowedMethods(Arrays.asList("*")); configuration.setAllowedHeaders(Arrays.asList("*")); configuration.setMaxAge(Duration.ofHours(1)); source.registerCorsConfiguration("/**",configuration); return source; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      通過 CorsConfigurationSource 實例對跨域信息作出詳細配置,例如允許的請求來源、允許的請求方法、允許通過的請求頭、探測請求的有效期、需要處理的路徑等等。

      使用這種方式就可以去掉第二小節的跨域配置了。

      4.OAuth2

      還有一種情況就是 OAuth2 允許跨域,如果用戶要訪問 OAuth2 端點,例如 /oauth/token ,出現了跨域該怎么配置呢?

      這個解決方案松哥在之前的 【用 Swagger 測試接口,怎么在請求頭中攜帶 Token?】 一文中已經有過介紹,主要是配置一個 CorsFilter,大家可以參考該篇文章,我這里就把核心配置類列出來:

      @Configuration public class GlobalCorsConfiguration { @Bean public CorsFilter corsFilter() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowCredentials(true); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(urlBasedCorsConfigurationSource); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      然后在 SecurityConfig 中開啟跨域支持:

      @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) public class SecurityConfig extends WebSecurityConfigurerAdapter { ... ... @Override protected void configure(HttpSecurity http) throws Exception { http .requestMatchers().antMatchers(HttpMethod.OPTIONS, "/oauth/**") .and() .csrf().disable().formLogin() .and() .cors(); } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      5.小結

      好啦,今天主要和小伙伴們總結了一下 Spring Boot 中三種跨域的場景,不知道大家有沒有 GET 到呢?如果覺得有收獲,記得點個在看鼓勵下松哥哦~

      Spring Spring Boot 網絡

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:《Office 2019高效辦公三合一從入門到精通 : 視頻自學版》 —3.8實戰演練—設置并規范合同格式
      下一篇:WPS表格技巧—如何利用形狀來制作創意表格(wps這么制作表格)
      相關文章
      亚洲中文字幕久久精品无码A| 亚洲欧洲自拍拍偷午夜色| 国产亚洲中文日本不卡二区| 亚洲欧洲日产国码二区首页| 亚洲国产人成网站在线电影动漫| 久久亚洲国产中v天仙www| 日韩精品亚洲aⅴ在线影院| 亚洲色偷偷综合亚洲AV伊人| 亚洲国产精品一区二区第一页免| 亚洲av片一区二区三区| 亚洲精品网站在线观看不卡无广告| 亚洲精品视频在线观看你懂的| 亚洲精品WWW久久久久久| 亚洲精品岛国片在线观看| 亚洲日韩涩涩成人午夜私人影院| 亚洲精品专区在线观看| 中文字幕第一页亚洲| 亚洲日韩aⅴ在线视频| 亚洲av综合av一区| 亚洲午夜在线电影| 亚洲制服丝袜一区二区三区| 在线观看亚洲AV日韩AV| 亚洲精品国产精品| 五月天婷亚洲天综合网精品偷| 亚洲äv永久无码精品天堂久久 | 亚洲综合日韩久久成人AV| 亚洲女同成av人片在线观看| 国产亚洲一区二区三区在线观看| 久久精品国产亚洲AV果冻传媒| 亚洲丝袜美腿视频| 亚洲伊人久久大香线焦| 国产亚洲精品bv在线观看| 美国毛片亚洲社区在线观看| 亚洲精品国产V片在线观看 | 亚洲国产最大av| 久久久久亚洲国产AV麻豆 | 国产精品亚洲mnbav网站| 国产∨亚洲V天堂无码久久久| 亚洲国产精品久久久久婷婷老年 | 亚洲人成人网站在线观看| 国产成人精品日本亚洲专区61|