版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第SpringBoot之跨域過(guò)濾器配置允許跨域訪問(wèn)方式目錄SpringBoot跨域過(guò)濾器配置允許跨域訪問(wèn)跨域請(qǐng)求問(wèn)題背景跨域過(guò)濾器跨域功能改進(jìn)SpringBoot跨域設(shè)置(CORS)一、什么是跨域二、跨域資源共享(CORS)1.簡(jiǎn)單請(qǐng)求2.非簡(jiǎn)單請(qǐng)求三、SpringBoot設(shè)置CORS
SpringBoot跨域過(guò)濾器配置允許跨域訪問(wèn)
跨域請(qǐng)求
當(dāng)一個(gè)資源從與該資源本身所在的服務(wù)器不同的域或端口請(qǐng)求一個(gè)資源時(shí),資源會(huì)發(fā)起一個(gè)跨域HTTP請(qǐng)求。
出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源HTTP請(qǐng)求。例如,XMLHttpRequest和FetchAPI遵循同源策略。這意味著使用這些API的Web應(yīng)用程序只能從加載應(yīng)用程序的同一個(gè)域請(qǐng)求HTTP資源,除非使用CORS頭文件。
問(wèn)題背景
如果前端提示Access-Control-Allow-Origin問(wèn)題
XMLHttpRequestcannotloadhttp://xxxxxxxxxx/.NoAccess-Control-Allow-Originheaderispresentontherequestedresource.Originnullisthereforenotallowedaccess.
跨域過(guò)濾器
那么需要再SpringBoot2配置跨域過(guò)濾器允許跨域訪問(wèn)。
importjava.io.IOException;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.springframework.stereotype.Component;
@Component
publicclassCorsFilterimplementsFilter{
@Override
publicvoiddoFilter(ServletRequestreq,ServletResponseres,FilterChainchain)throwsIOException,ServletException{
HttpServletRequestrequest=(HttpServletRequest)req;
HttpServletResponseresponse=(HttpServletResponse)res;
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Methods","POST,GET,OPTIONS,DELETE,PUT,GET");
response.setHeader("Access-Control-Max-Age","3600");
response.setHeader("Access-Control-Allow-Headers","x-requested-with");
chain.doFilter(req,res);
}
@Override
publicvoidinit(FilterConfigfilterConfig){}
@Override
publicvoiddestroy(){}
}
跨域功能改進(jìn)
如果需要顯示跨域地址,還可以在里面加上訪問(wèn)來(lái)源打印語(yǔ)句,供排查
StringcurOrigin=request.getHeader("Origin");
System.out.println("###跨域過(guò)濾器-當(dāng)前訪問(wèn)來(lái)源-"+curOrigin+"###");
如果需要跨域權(quán)限,可以判斷一下來(lái)源
StringcurOrigin=request.getHeader("Origin");
System.out.println("###跨域過(guò)濾器-當(dāng)前訪問(wèn)來(lái)源-"+curOrigin+"###");
if(curOrigin.indexOf(":8080")-1){
response.setHeader("Access-Control-Allow-Origin","*");
}
關(guān)于跨域訪問(wèn)更專業(yè)的內(nèi)容,可以訪問(wèn)Mozilla官方的一個(gè)關(guān)于CROS文章
/zh-CN/docs/Web/HTTP/Access_control_CORS
SpringBoot跨域設(shè)置(CORS)
一、什么是跨域
請(qǐng)求url的協(xié)議、域名、端口三者有任意一個(gè)不同即為跨域??缬騿?wèn)題是因?yàn)闉g覽器的同源策略的限制而產(chǎn)生的。
同源:請(qǐng)求url的協(xié)議、域名、端口三者都相同即為同源(同一個(gè)域)。同源策略:同源策略(Sameoriginpolicy)是一種約定,他是瀏覽器最核心也最基本的安全功能。同源策略會(huì)阻止非同源(同一個(gè)域)的內(nèi)容進(jìn)行交互。
同源策略的限制:
無(wú)法讀取非同源網(wǎng)頁(yè)的Cookie、LocalStorage和IndexedDB無(wú)法接觸非同源網(wǎng)頁(yè)的DOM無(wú)法向非同源地址發(fā)送AJAX請(qǐng)求
瀏覽器的同源策略會(huì)限制跨域請(qǐng)求,限制的方式一般有兩種:
瀏覽器限制發(fā)起跨域請(qǐng)求;跨域請(qǐng)求可以正常發(fā)起,但是返回的結(jié)果被瀏覽器攔截了。
一般瀏覽器都是第二種方式限制跨域請(qǐng)求,那就是說(shuō)請(qǐng)求已到達(dá)服務(wù)器,并有可能對(duì)數(shù)據(jù)庫(kù)里的數(shù)據(jù)進(jìn)行了操作,但是返回的結(jié)果被瀏覽器攔截了,那么我們就獲取不到返回結(jié)果,這是一次失敗的請(qǐng)求,但是可能對(duì)數(shù)據(jù)庫(kù)里的數(shù)據(jù)產(chǎn)生了影響。
為了防止這種情況的發(fā)生,規(guī)范要求,對(duì)這種可能對(duì)服務(wù)器數(shù)據(jù)產(chǎn)生副作用的HTTP請(qǐng)求方法,瀏覽器必須先使用OPTIONS方法發(fā)起一個(gè)預(yù)檢請(qǐng)求,從而獲知服務(wù)器是否允許該跨域請(qǐng)求:如果允許,就發(fā)送帶數(shù)據(jù)的真實(shí)請(qǐng)求;如果不允許,則阻止發(fā)送帶數(shù)據(jù)的真實(shí)請(qǐng)求。
二、跨域資源共享(CORS)
解決非同源內(nèi)容無(wú)法交互的問(wèn)題,目前主流的解決方案就是:CORS(跨域資源共享)。
跨域資源共享(Cross-originResourceSharing)簡(jiǎn)稱CORS,它突破了一個(gè)請(qǐng)求在瀏覽器發(fā)出只能在同源的情況下向服務(wù)器獲取數(shù)據(jù)的限制。
CORS約定服務(wù)器端和瀏覽器在HTTP協(xié)議之上,通過(guò)一些額外HTTP頭部信息,進(jìn)行跨域資源共享的協(xié)商。服務(wù)器端和瀏覽器都必需遵循規(guī)范中的要求。
CORS把HTTP的跨域請(qǐng)求分成兩類,簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求,不同請(qǐng)求按照不同的策略進(jìn)行跨域資源共享協(xié)商。
1.簡(jiǎn)單請(qǐng)求
簡(jiǎn)單跨域請(qǐng)求需滿足的條件:
1.請(qǐng)求方法是GET、HEAD或者POST(POST時(shí),Content-Type的值必須是application/x-www-form-urlencoded、multipart/form-data、text/plain中的一個(gè)值);
2.請(qǐng)求中沒(méi)有自定義HTTP請(qǐng)求頭。
HTTP頭只能時(shí)下面這些字段:
AcceptAccept-LanguageContent-LanguageDPRDownlinkSave-DataViewport-WidthWidthContent-Type
以上兩點(diǎn)都滿足才是簡(jiǎn)單跨域請(qǐng)求。
對(duì)于簡(jiǎn)單跨域請(qǐng)求,處理方式如下:
1.瀏覽器要做的就是在HTTP請(qǐng)求頭中添加Origin,將JavaScript腳本所在域填充進(jìn)去,向其他域的服務(wù)器請(qǐng)求資源。
Origin:
Origin字段用來(lái)說(shuō)明,本次請(qǐng)求來(lái)自哪個(gè)源(協(xié)議+域名+端口)。服務(wù)器根據(jù)這個(gè)值,決定是否同意這次請(qǐng)求。
2.服務(wù)器端收到一個(gè)簡(jiǎn)單跨域請(qǐng)求后,根據(jù)資源權(quán)限配置,在響應(yīng)頭中添加Access-Control-Allow-Origin。
如果Origin指定的源,不在許可范圍內(nèi),服務(wù)器會(huì)返回一個(gè)正常的HTTP回應(yīng)。但這個(gè)響應(yīng)頭信息沒(méi)有包含Access-Control-Allow-Origin字段,瀏覽器就知道該域名不在許可范圍內(nèi)。
如果Origin指定的域名在許可范圍內(nèi),服務(wù)器返回的響應(yīng),會(huì)多出幾個(gè)頭信息字段:
Access-Control-Allow-Origin:
Access-Control-Allow-Credentials:true
Access-Control-Expose-Headers:My-Token
Access-Control-Allow-Origin:該字段是必須的。它的值要么是請(qǐng)求時(shí)Origin字段的值,要么是一個(gè)*值,表示接受任意域名的請(qǐng)求。Access-Control-Allow-Credentials:該字段是可選的。它的值是一個(gè)布爾值,表示是否允許發(fā)送Cookie。默認(rèn)情況下,Cookie不包括在CORS請(qǐng)求之中。設(shè)為true,即表示服務(wù)器明確許可,Cookie可以包含在請(qǐng)求中,一起發(fā)給服務(wù)器。這個(gè)值也只能設(shè)為true,如果服務(wù)器不要瀏覽器發(fā)送Cookie,刪除該字段即可。Access-Control-Expose-Headers:該字段是可選的。CORS請(qǐng)求時(shí),XMLHttpRequest對(duì)象的getResponseHeader()方法只能拿到6個(gè)基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定。
3.瀏覽器收到響應(yīng)后,通過(guò)獲取響應(yīng)頭中的Access-Control-Allow-Origin字段,來(lái)判斷如果當(dāng)前域已經(jīng)得到授權(quán),則將結(jié)果返回給JavaScript。否則瀏覽器忽略此次響應(yīng)。
2.非簡(jiǎn)單請(qǐng)求
非簡(jiǎn)單跨域請(qǐng)求需滿足的條件:
除GET、HEAD和POST(Content-Type的值是:application/x-www-form-urlencoded、multipart/form-data、text/plain中的一個(gè)值)以外的其他HTTP方法如:PUT、DELETE、TRACE、PATCH、POST(Content-Type的值是:application/json)。請(qǐng)求中有自定義HTTP頭部。
以上兩點(diǎn)只要至少滿足其中一點(diǎn)就是非簡(jiǎn)單跨域請(qǐng)求。
對(duì)于非簡(jiǎn)單跨域請(qǐng)求,處理方式如下:
1.瀏覽器在發(fā)送真實(shí)HTTP請(qǐng)求之前先發(fā)送一個(gè)OPTIONS的預(yù)檢請(qǐng)求,檢測(cè)服務(wù)器端是否支持真實(shí)請(qǐng)求進(jìn)行跨域資源訪問(wèn)。
真實(shí)請(qǐng)求的信息在OPTIONS請(qǐng)求中通過(guò)請(qǐng)求頭中的Access-Control-Request-Method和Access-Control-Request-Headers字段來(lái)描述。此外與簡(jiǎn)單跨域請(qǐng)求一樣,請(qǐng)求頭中也會(huì)有Origin字段。
Origin:
Access-Control-Request-Method:PUT
Access-Control-Request-Headers:Header1,Header2
Origin:必須字段,用于指定請(qǐng)求源。Access-Control-Request-Method:必須字段,用于描述真實(shí)請(qǐng)求的方法(PUT、DELETE等)。Access-Control-Request-Headers:指定真實(shí)請(qǐng)求會(huì)額外發(fā)送的請(qǐng)求頭字段信息。
2.服務(wù)器端接到預(yù)檢請(qǐng)求后,會(huì)檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段,檢驗(yàn)是否允許跨源請(qǐng)求。
如果不允許該跨域請(qǐng)求,會(huì)返回一個(gè)正常的HTTP回應(yīng),但這個(gè)響應(yīng)頭信息沒(méi)有包含Access-Control-Allow-Origin字段,瀏覽器就知道該域名不在許可范圍內(nèi)。
如果允許該跨域請(qǐng)求,就會(huì)在響應(yīng)頭中放入Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers,分別表示允許跨域資源請(qǐng)求的域、請(qǐng)求方法和請(qǐng)求頭。此外,服務(wù)器端還可以在響應(yīng)頭中放入Access-Control-Max-Age,允許瀏覽器在指定時(shí)間內(nèi),無(wú)需再發(fā)送預(yù)檢請(qǐng)求進(jìn)行協(xié)商,直接用本次協(xié)商結(jié)果即可。
Access-Control-Allow-Origin:
Access-Control-Allow-Methods:GET,POST,PUT
Access-Control-Allow-Headers:Header1,Header2,Header3
Access-Control-Allow-Credentials:true
Access-Control-Max-Age:1728000
Access-Control-Allow-Methods:該字段必需,它的值是逗號(hào)分隔的一個(gè)字符串,表明服務(wù)器支持的所有跨域請(qǐng)求的方法。注意,返回的是所有支持的方法,而不單是瀏覽器請(qǐng)求的那個(gè)方法。這是為了避免多次預(yù)檢請(qǐng)求。Access-Control-Allow-Headers:如果瀏覽器請(qǐng)求包括Access-Control-Request-Headers字段,則Access-Control-Allow-Headers字段是必需的。它也是一個(gè)逗號(hào)分隔的字符串,表明服務(wù)器支持的所有頭信息字段,不限于瀏覽器在預(yù)檢中請(qǐng)求的字段。Access-Control-Allow-Credentials:該字段與簡(jiǎn)單請(qǐng)求時(shí)的含義相同。它的值是一個(gè)布爾值,表示是否允許發(fā)送Cookie。默認(rèn)情況下,Cookie不包括在CORS請(qǐng)求之中。設(shè)為true,即表示服務(wù)器明確許可,Cookie可以包含在請(qǐng)求中,一起發(fā)給服務(wù)器。這個(gè)值也只能設(shè)為true,如果服務(wù)器不要瀏覽器發(fā)送Cookie,刪除該字段即可。Access-Control-Max-Age:該字段可選,用來(lái)指定本次預(yù)檢請(qǐng)求的有效期,單位為秒。上面結(jié)果中,有效期是20天(1728000秒),即允許緩存該條回應(yīng)1728000秒(即20天),在此期間,不用發(fā)出另一條預(yù)檢請(qǐng)求。
瀏覽器根據(jù)OPTIONS請(qǐng)求返回的結(jié)果來(lái)決定是否繼續(xù)發(fā)送真實(shí)的請(qǐng)求進(jìn)行跨域資源訪問(wèn)。這個(gè)過(guò)程對(duì)真實(shí)請(qǐng)求的調(diào)用者來(lái)說(shuō)是透明的。
三、SpringBoot設(shè)置CORS
SpringBoot設(shè)置CORS的的本質(zhì)都是通過(guò)設(shè)置響應(yīng)頭信息來(lái)告訴前端該請(qǐng)求是否支持跨域。
SpringBoot設(shè)置CORS的方式主要有以下三種。
1.配置過(guò)濾器CorsFilter
@Configuration
publicclassCorsConfig{
@Bean
CorsFiltercorsFilter(){
CorsConfigurationconfiguration=newCorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSourcesource=newUrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",configuration);
returnnewCorsFilter(source);
}
}
2.實(shí)現(xiàn)接口WebMvcConfigurer
@Configuration
publicclassWebMvcConfigimplementsWebMvcConfigurer{
@Override
publicvoidaddCorsMappings(CorsRegistryregistry){
registry.addMapping("/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("*")
.allowCredentials(true);
}
}
3.使用注解@CrossOrigin
@CrossOrigin注解可以用在類或者方法上
用在控制器類上,表示該類的所有方法都允許跨域
@RestController
@CrossOrigin
publicclassTestController{
@GetMapping("test")
publicStringtest(){
return"success";
}
}
用在控制器方法上,表示該方法都允許跨域
@RestController
publicclassTestController{
@CrossOrigin
@GetMapping("test")
publicStringtest(){
return"success";
}
}
@CrossOrigin注解源碼
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public@interfaceCrossOrigin{
/**
*這origins和value是一樣的
*允許來(lái)源域名的列表,例如,匹配的域名是跨域預(yù)請(qǐng)求Response頭中的Access-Control-Aloow_origin字段值。
*不設(shè)置確切值時(shí)默認(rèn)支持所有域名跨域訪問(wèn)。
*/
@AliasFor("origins")
String[]value()default{};
@AliasFor("value")
String[]origins()default{};
/**
*高版本下Spring2.4.4使用originPatterns而不是value和origins
*/
String[]originPatterns()default{};
/**
*跨域請(qǐng)求中允許的請(qǐng)求頭中的字段類型,該值對(duì)應(yīng)跨域預(yù)請(qǐng)求Response頭中的Access-Control-Allow-Headers字段值。
*
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 小區(qū)消防安全評(píng)估指南
- 安全生產(chǎn)典范企業(yè)講解
- 2025-2026人教版小學(xué)二年級(jí)語(yǔ)文期末測(cè)試卷上
- 結(jié)構(gòu)專業(yè)考試題及答案
- 2025-2026人教版三年級(jí)語(yǔ)文上學(xué)期卷
- 腸道菌群與NAFLD肝硬化PHG:MDT調(diào)節(jié)策略
- 2025-2026一年級(jí)語(yǔ)文上學(xué)期期末測(cè)試卷
- 腸狹窄術(shù)后腹腔感染的處理策略
- 腸梗阻合并糖尿病患者的血糖管理策略
- 衛(wèi)生院執(zhí)業(yè)監(jiān)督管理制度
- 安全生產(chǎn)目標(biāo)及考核制度
- (2026版)患者十大安全目標(biāo)(2篇)
- 2026年北大拉丁語(yǔ)標(biāo)準(zhǔn)考試試題
- 臨床護(hù)理操作流程禮儀規(guī)范
- 2025年酒店總經(jīng)理年度工作總結(jié)暨戰(zhàn)略規(guī)劃
- 空氣栓塞課件教學(xué)
- 2025年國(guó)家市場(chǎng)監(jiān)管總局公開(kāi)遴選公務(wù)員面試題及答案
- 肌骨康復(fù)腰椎課件
- 患者身份識(shí)別管理標(biāo)準(zhǔn)
- 2025年10月自考04184線性代數(shù)經(jīng)管類試題及答案含評(píng)分參考
- 2025年勞動(dòng)保障協(xié)理員三級(jí)技能試題及答案
評(píng)論
0/150
提交評(píng)論