基于SpringBoot解決CORS跨域的問題(@CrossOrigin)
一、關(guān)于跨域介紹
在前后分離的架構(gòu)下,跨域問題難免會(huì)遇見比如,站點(diǎn) http://domain-a.com 的某 HTML 頁面通過 的 src 請(qǐng)求 http://domain-b.com/image.jpg。
網(wǎng)絡(luò)上的許多頁面都會(huì)加載來自不同域的CSS樣式表,圖像和腳本等資源。
出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源HTTP請(qǐng)求。
例如,XMLHttpRequest和Fetch API遵循同源策略。
這意味著使用這些API的Web應(yīng)用程序只能從加載應(yīng)用程序的同一個(gè)域請(qǐ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使用場(chǎng)景要求
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>這些值都顯示在請(qǐng)求頭中的Access-Control-Allow-Origin
* "*"代表所有域的請(qǐng)求都支持
* <p>如果沒有定義,所有請(qǐng)求的域都支持
* @see #value
*/
@AliasFor("value")
String[] origins() default {};
/**
* 允許請(qǐng)求頭重的header,默認(rèn)都支持
*/
String[] allowedHeaders() default {};
/**
* 響應(yīng)頭中允許訪問的header,默認(rèn)為空
*/
String[] exposedHeaders() default {};
/**
* 請(qǐng)求支持的方法,例如"{RequestMethod.GET, RequestMethod.POST}"}。
* 默認(rèn)支持RequestMapping中設(shè)置的方法
*/
RequestMethod[] methods() default {};
/**
* 是否允許cookie隨請(qǐng)求發(fā)送,使用時(shí)必須指定具體的域
*/
String allowCredentials() default "";
/**
* 預(yù)請(qǐng)求的結(jié)果的有效期,默認(rèn)30分鐘
*/
long maxAge() default -1;
}
3、@CrossOrigin使用
Spring Boot下的請(qǐng)求處理控制器
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: 請(qǐng)求處理控制器
* @author 淺然
* @date 2018/7/2022:18
**/
@RestController
//實(shí)現(xiàn)跨域注解
//origin="*"代表所有域名都可訪問
//maxAge飛行前響應(yīng)的緩存持續(xù)時(shí)間的最大年齡,簡(jiǎn)單來說就是Cookie的有效期 單位為秒
//若maxAge是負(fù)數(shù),則代表為臨時(shí)Cookie,不會(huì)被持久化,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)代碼
}
}
后臺(tái)返回的數(shù)據(jù)

前端跨域請(qǐng)求
<!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="測(cè)試" 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) {
//請(qǐng)求失敗時(shí)執(zhí)行該函數(shù)
alert("請(qǐng)求數(shù)據(jù)失敗!");
}
});
$("#usermessage").text(getdata)
}
</script>
</body>
</html>
這樣就解決了跨域問題,獲取了后臺(tái)的數(shù)據(jù)

參考
補(bǔ)充:springboot的@CrossOrigin("*")跨域仍然失效
項(xiàng)目中偶爾遇到即使加了@CrossOrigin跨域失?。?/p>
第一次遇到時(shí)間有限沒解決:前端直接添加跨域處理。
jQuery.support.cors = true;
后續(xù)第二次遇到該問題,作為后端不能讓前端解決跨域問題。
debug詳細(xì)查找原因:發(fā)現(xiàn)在自定義攔截器返回失敗,跨域失敗。
明白該問題:需要以下知識(shí)。
(mvc攔截器的鏈路模式)
(Cors攔截器加載)
(自定義的攔截器加載)
(攔截器的加載順序)
因?yàn)閿r截器是鏈路模式:CrossOrigin也是攔截器在自定義攔截器之后。所以在自定義攔截器失敗后,處理
跨域的攔截器未處理,造成跨域失敗。
解決該問題的辦法:
添加filter ,因?yàn)镕ilter優(yōu)先于攔截器執(zhí)行,所以自己創(chuàng)建的攔截器不會(huì)影響跨域處理。
@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升級(jí)到2.2.0,在新版本的springmvc中,把cors攔截添加到了攔截器的第一位,所以不會(huì)有該問題。
如果允許可以直接升級(jí)springboot或mvc版本。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
- vue+springboot實(shí)現(xiàn)項(xiàng)目的CORS跨域請(qǐng)求
- 詳解springboot設(shè)置cors跨域請(qǐng)求的兩種方式
- Spring boot 和Vue開發(fā)中CORS跨域問題解決
- Springboot處理CORS跨域請(qǐng)求的三種方法
- 詳解springboot解決CORS跨域的三種方式
- Springboot處理配置CORS跨域請(qǐng)求時(shí)碰到的坑
- Springboot跨域CORS處理實(shí)現(xiàn)原理
- SpringBoot跨域Jsonp和Cors的方法
- Spring Boot如何通過CORS處理跨域問題
- springboot跨域CORS處理代碼解析
- SpringBoot使用CORS實(shí)現(xiàn)無縫跨域的方法實(shí)現(xiàn)
相關(guān)文章
SpringBoot手動(dòng)使用EhCache的方法示例
本篇文章主要介紹了SpringBoot手動(dòng)使用EhCache的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02
Jenkins遷移job插件Job Import Plugin流程詳解
這篇文章主要介紹了Jenkins遷移job插件Job Import Plugin流程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
SpringBoot利用注解來實(shí)現(xiàn)Redis分布式鎖
有些業(yè)務(wù)請(qǐng)求,屬于耗時(shí)操作,需要加鎖,防止后續(xù)的并發(fā)操作,同時(shí)對(duì)數(shù)據(jù)庫的數(shù)據(jù)進(jìn)行操作,需要避免對(duì)之前的業(yè)務(wù)造成影響。本文將利用注解來實(shí)現(xiàn)Redis分布式鎖,需要的可以參考一下2022-09-09
Javaweb實(shí)現(xiàn)上傳下載文件的多種方法
本篇文章主要介紹了Javaweb實(shí)現(xiàn)上傳下載文件,有多種實(shí)現(xiàn)方式,需要的朋友可以參考下。2016-10-10
Idea中SpringBoot多模塊項(xiàng)目的建立實(shí)現(xiàn)
這篇文章主要介紹了Idea中SpringBoot多模塊項(xiàng)目的建立實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06

