基于SpringBoot解決CORS跨域的問題(@CrossOrigin)
一、關(guān)于跨域介紹
在前后分離的架構(gòu)下,跨域問題難免會遇見比如,站點 http://domain-a.com 的某 HTML 頁面通過 的 src 請求 http://domain-b.com/image.jpg。
網(wǎng)絡(luò)上的許多頁面都會加載來自不同域的CSS樣式表,圖像和腳本等資源。
出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源HTTP請求。
例如,XMLHttpRequest和Fetch API遵循同源策略。
這意味著使用這些API的Web應(yīng)用程序只能從加載應(yīng)用程序的同一個域請求HTTP資源,除非使用CORS頭文件。
跨域的體現(xiàn),在于它的域名不同或者端口不同,但要注意以下的形式為非跨域模式
http://www.example.com/index.html ==> http://www.example.com/login.html
二、Spring Boot跨域(@CrossOrigin)
當(dāng)然這里雖然指SpringBoot但是SpringMVC也是一樣的,要求在Spring4.2及以上的版本
1、@CrossOrigin使用場景要求
jdk1.8+
Spring4.2+
2、@CrossOrigin源碼解析(翻譯參考網(wǎng)絡(luò),文末列出參考地址)
@Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface CrossOrigin { String[] DEFAULT_ORIGINS = { "*" }; String[] DEFAULT_ALLOWED_HEADERS = { "*" }; boolean DEFAULT_ALLOW_CREDENTIALS = true; long DEFAULT_MAX_AGE = 1800; /** * 同origins屬性一樣 */ @AliasFor("origins") String[] value() default {}; /** * 所有支持域的集合,例如"http://domain1.com"。 * <p>這些值都顯示在請求頭中的Access-Control-Allow-Origin * "*"代表所有域的請求都支持 * <p>如果沒有定義,所有請求的域都支持 * @see #value */ @AliasFor("value") String[] origins() default {}; /** * 允許請求頭重的header,默認都支持 */ String[] allowedHeaders() default {}; /** * 響應(yīng)頭中允許訪問的header,默認為空 */ String[] exposedHeaders() default {}; /** * 請求支持的方法,例如"{RequestMethod.GET, RequestMethod.POST}"}。 * 默認支持RequestMapping中設(shè)置的方法 */ RequestMethod[] methods() default {}; /** * 是否允許cookie隨請求發(fā)送,使用時必須指定具體的域 */ String allowCredentials() default ""; /** * 預(yù)請求的結(jié)果的有效期,默認30分鐘 */ long maxAge() default -1; }
3、@CrossOrigin使用
Spring Boot下的請求處理控制器
package com.example.demo.controller; import com.example.demo.domain.User; import com.example.demo.service.IUserFind; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @Title: UserController * @ProjectName demo * @Description: 請求處理控制器 * @author 淺然 * @date 2018/7/2022:18 **/ @RestController //實現(xiàn)跨域注解 //origin="*"代表所有域名都可訪問 //maxAge飛行前響應(yīng)的緩存持續(xù)時間的最大年齡,簡單來說就是Cookie的有效期 單位為秒 //若maxAge是負數(shù),則代表為臨時Cookie,不會被持久化,Cookie信息保存在瀏覽器內(nèi)存中,瀏覽器關(guān)閉Cookie就消失 @CrossOrigin(origins = "*",maxAge = 3600) public class UserController { @Resource private IUserFind userFind; @GetMapping("finduser") public User finduser(@RequestParam(value="id") Integer id){ //此處省略相應(yīng)代碼 } }
后臺返回的數(shù)據(jù)
前端跨域請求
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>demo</title> <script type="text/javascript" src="js/jquery-3.3.1.min.js" ></script> </head> <body> <input type="button" value="測試" onclick="ajaxloding()" /> <div id="usermessage"></div> <script> var getdata=0; function ajaxloding(){ $.ajax({ async:false, type:"get", url:"http://localhost:8080/api/finduser?id=1", contentType: "application/x-www-form-urlencoded", dataType: "json", data: {}, success:function(result){ getdata=result.name }, error: function (errorMsg) { //請求失敗時執(zhí)行該函數(shù) alert("請求數(shù)據(jù)失敗!"); } }); $("#usermessage").text(getdata) } </script> </body> </html>
這樣就解決了跨域問題,獲取了后臺的數(shù)據(jù)
參考
補充:springboot的@CrossOrigin("*")跨域仍然失效
項目中偶爾遇到即使加了@CrossOrigin跨域失敗:
第一次遇到時間有限沒解決:前端直接添加跨域處理。
jQuery.support.cors = true;
后續(xù)第二次遇到該問題,作為后端不能讓前端解決跨域問題。
debug詳細查找原因:發(fā)現(xiàn)在自定義攔截器返回失敗,跨域失敗。
明白該問題:需要以下知識。
(mvc攔截器的鏈路模式)
(Cors攔截器加載)
(自定義的攔截器加載)
(攔截器的加載順序)
因為攔截器是鏈路模式:CrossOrigin也是攔截器在自定義攔截器之后。所以在自定義攔截器失敗后,處理
跨域的攔截器未處理,造成跨域失敗。
解決該問題的辦法:
添加filter ,因為Filter優(yōu)先于攔截器執(zhí)行,所以自己創(chuàng)建的攔截器不會影響跨域處理。
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.setAllowCredentials(true); config.addAllowedMethod("*"); config.addAllowedHeader("*"); UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); return new CorsFilter(configSource); } }
二:springboot升級到2.2.0,在新版本的springmvc中,把cors攔截添加到了攔截器的第一位,所以不會有該問題。
如果允許可以直接升級springboot或mvc版本。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
- vue+springboot實現(xiàn)項目的CORS跨域請求
- 詳解springboot設(shè)置cors跨域請求的兩種方式
- Spring boot 和Vue開發(fā)中CORS跨域問題解決
- Springboot處理CORS跨域請求的三種方法
- 詳解springboot解決CORS跨域的三種方式
- Springboot處理配置CORS跨域請求時碰到的坑
- Springboot跨域CORS處理實現(xiàn)原理
- SpringBoot跨域Jsonp和Cors的方法
- Spring Boot如何通過CORS處理跨域問題
- springboot跨域CORS處理代碼解析
- SpringBoot使用CORS實現(xiàn)無縫跨域的方法實現(xiàn)
相關(guān)文章
詳解spring cloud ouath2中的資源服務(wù)器
這篇文章主要介紹了spring cloud ouath2中的資源服務(wù)器的相關(guān)知識,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02Hibernate框架數(shù)據(jù)分頁技術(shù)實例分析
這篇文章主要介紹了Hibernate框架數(shù)據(jù)分頁技術(shù),結(jié)合實例形式分析了Hibernate框架實現(xiàn)數(shù)據(jù)分頁的原理,步驟與相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2016-03-03JAVA將中文轉(zhuǎn)換為拼音簡單實現(xiàn)方法
拼音轉(zhuǎn)換是中文處理的常見需求,TinyPinyin、HanLP、pinyin4j是常用的本地拼音轉(zhuǎn)換庫,各有特點,開發(fā)者可根據(jù)具體需求選擇合適的拼音轉(zhuǎn)換工具,需要的朋友可以參考下2024-10-10Java前后端任意參數(shù)類型轉(zhuǎn)換方式(Date、LocalDateTime、BigDecimal)
這篇文章主要介紹了Java前后端任意參數(shù)類型轉(zhuǎn)換方式(Date、LocalDateTime、BigDecimal),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06