SpringBoot解決跨域的超實(shí)用方案分享
一、驗(yàn)證跨域
模擬前端地址:http://localhost:8080/index.html
后端接口地址:http://localhost:8081/auth/test/cors
思路:啟動(dòng)兩個(gè)springboot項(xiàng)目:8080端口和8081端口,在8080端口的靜態(tài)資源目錄index.html中,對8081端口的接口發(fā)起請求,因?yàn)槎丝诓煌詫儆诳缬?,從而就可以?yàn)證不同請求(
POST或OPTIONS等方法)是否報(bào)CORS error !
1. 添加index.html
在 tg-book-web的resources下,新建static\index.html
邏輯:使用ajax發(fā)送請求,調(diào)用8081的/auth/test/cors接口,如果執(zhí)行成功,將結(jié)果輸出到id="result"的div下,如下代碼是post請求,后面還會(huì)改成options請求測試.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<div id="result">
</div>
</body>
<script type="text/javascript">
$.ajax({
url: 'http://localhost:8081/auth/test/cors',
method: 'post',
success: function (res) {
console.log(res)
$('#result').append('<p>' + res['message'] + '</p>')
}
})
</script>
</html>對index.html不進(jìn)行接口身份認(rèn)證
因?yàn)槲覀冊黾恿松矸菡J(rèn)證AuthInterceptor,所以需要在AuthInterceptor的preHandle過濾掉index.html,如下:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("AuthInterceptor.preHandle:" + request.getServletPath());
if (request.getServletPath().startsWith("/index.html")) {
return true;
}
...其它代碼
}2. 增加/auth/test/cors接口
AuthController下增加接口
@PostMapping("/test/cors")
public TgResult<String> testCors() {
return TgResult.ok();
}同樣,將/auth/test/cors也不進(jìn)行接口身份認(rèn)證.
排除身份認(rèn)證是為了更好的測試跨域,所以同樣寫在排除"/auth/login"的位置.
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**")
// 排除的請求路徑
.excludePathPatterns("/auth/login", "/auth/test/cors");3. IDEA啟動(dòng)多個(gè)springboot項(xiàng)目
關(guān)于如何使用IDEA啟動(dòng)多個(gè)springboot項(xiàng)目,我就不演示了,我啟動(dòng)了8080和8081兩個(gè)端口:

4. 驗(yàn)證POST方法
在瀏覽器打開 http://localhost:8080/index.html,如下圖:

可以看到,8080/index.html通過ajax請求了8081的接口,返回200,說明支持POST請求跨域!
5. 驗(yàn)證OPTIONS方法
OK,正如我開頭所說,@CrossOrigin注解對options方法并沒有支持跨域,我們來試一試!
只需將index.html中的 【 method: ‘post’】改為【 method: ‘options’】,重啟8080服務(wù),然后用同樣的方法測試,如下,報(bào)CORS error了 ??

詳細(xì)報(bào)錯(cuò):

二、攔截器方案
SpringBoot中使用攔截器需要2步:
- 定義攔截器
- 注冊攔截器,并指定攔截規(guī)則
定義攔截器
新增一個(gè)攔截器類 CorsInterceptor 實(shí)現(xiàn) HandlerInterceptor 接口
package org.tg.book.web.interceptor;
@Component
public class CorsInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 允許跨域源,全部允許為*,否則寫允許請求的源ip
if (StringUtils.isEmpty(request.getHeader("Origin"))) {
response.setHeader("Access-Control-Allow-Origin", "*");
} else {
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
}
response.setHeader("Access-Control-Allow-Credentials", "true");
// 允許跨域方法:全部允許為*,否則寫具體的方法,例如:GET, POST, PUT, DELETE, OPTIONS
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "86400");
// 允許跨域請求頭
response.setHeader("Access-Control-Allow-Headers", "*");
// 如果是OPTIONS,不走后續(xù)操作,直接返回
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return false;
}
return true;
}
}- Access-Control-Allow-Origin: 允許跨域源,全部允許為*,否則寫允許請求的源ip。重點(diǎn):通常會(huì)使用白名單機(jī)制,只有request.getHeader(“Origin”) 在白名單中才允許跨域。
- Access-Control-Allow-Methods:允許跨域方法:全部允許為*,否則寫具體的方法,例如:GET, POST, PUT, DELETE, OPTIONS
注冊攔截器,并指定攔截規(guī)則
在原有的InterceptorConfig 中增加注入CorsInterceptor ,并將【跨域攔截器】 放在 【身份認(rèn)證攔截器】之前,如下:
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private CorsInterceptor corsInterceptor;
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 新增的跨域攔截器
registry.addInterceptor(corsInterceptor)
.addPathPatterns("/**");
// 身份認(rèn)證攔截器
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**")
// 排除的請求路徑
.excludePathPatterns("/auth/login");
}
}去除原來的 @CrossOrigin注解,然后驗(yàn)證,同樣,完全支持POST和OPTIONS方法!

三、過濾器方案
新增 CorsFilter 實(shí)現(xiàn)Filter接口
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
if (StringUtils.isEmpty(request.getHeader("Origin"))) {
response.setHeader("Access-Control-Allow-Origin", "*");
} else {
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
}
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "86400");
response.setHeader("Access-Control-Allow-Headers", "*");
// 如果是OPTIONS,不走后續(xù)操作,直接返回
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}新增配置類CorsConfig 注入 CorsFilter
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
return new CorsFilter();
}
}注意:測試時(shí)先注釋上面的 跨域攔截器,然后驗(yàn)證,完全支持POST和OPTIONS方法!
總結(jié)
今天我使用了兩種方案解決跨域:攔截器和過濾器方案,都是超實(shí)用的方案。另外,給你留個(gè)作業(yè)吧,都做成配置擴(kuò)展,而不是hard code,例如上面說到的白名單機(jī)制,實(shí)際就是配置一堆ip,其它也是同理,你可以把你的配置擴(kuò)展寫在留言區(qū)里,或者遇到的問題在留言區(qū)和我一起討論,感謝你的閱讀,也歡迎你把這篇文章分享給更多的朋友一起閱讀。
以上就是SpringBoot解決跨域的超實(shí)用方案分享的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot解決跨域的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java生成隨機(jī)姓名、性別和年齡的實(shí)現(xiàn)示例
這篇文章主要介紹了Java生成隨機(jī)姓名、性別和年齡的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
springboot 使用zookeeper實(shí)現(xiàn)分布式隊(duì)列的基本步驟
這篇文章主要介紹了springboot 使用zookeeper實(shí)現(xiàn)分布式隊(duì)列,通過ZooKeeper的協(xié)調(diào)和同步機(jī)制,多個(gè)應(yīng)用程序可以共享一個(gè)隊(duì)列,并按照先進(jìn)先出的順序處理隊(duì)列中的消息,需要的朋友可以參考下2023-08-08
Idea如何使用System.getenv()獲取環(huán)境變量的值
文章介紹了如何在Java中使用`System.getenv()`方法讀取環(huán)境變量的值,并提供了兩種配置環(huán)境變量的方法:啟動(dòng)項(xiàng)配置和系統(tǒng)環(huán)境變量配置,對于系統(tǒng)環(huán)境變量,文章特別指出需要重啟電腦或程序才能使其生效2024-11-11
maven assembly打包生成Java應(yīng)用啟動(dòng)腳本bat和sh的方法
springboot應(yīng)用通過maven插件appassembler-maven-plugi生成啟動(dòng)腳本bat和sh,這篇文章主要介紹了maven assembly打包生成Java應(yīng)用啟動(dòng)腳本bat和sh,需要的朋友可以參考下2022-11-11
springboot使用@Validated或@Valid注解校驗(yàn)參數(shù)方式
這篇文章主要介紹了springboot使用@Validated或@Valid注解校驗(yàn)參數(shù)方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
Java中的== 和equals()方法詳解與實(shí)例
本篇文章介紹了,在java中"==" 與equals方法的使用及其實(shí)例,需要的朋友可以參考下2017-04-04

