SpringBoot使用CORS解決無法跨域訪問問題的具體步驟
一、跨域問題
跨域問題指的是不同站點(diǎn)之間,使用 ajax 無法相互調(diào)用的問題。跨域問題本質(zhì)是瀏覽器的一種保護(hù)機(jī)制,它的初衷是為了保證用戶的安全,防止惡意網(wǎng)站竊取數(shù)據(jù)。但這個保護(hù)機(jī)制也帶來了新的問題,它的問題是給不同站點(diǎn)之間的正常調(diào)用,也帶來的阻礙,那怎么解決這個問題呢?接下來我們一起來看。
跨域三種情況
在請求時,如果出現(xiàn)了以下情況中的任意一種,那么它就是跨域請求:
- 協(xié)議不同,如 http 和 https;
- 域名不同;
- 端口不同。
也就是說,即使域名相同,如果一個使用的是 http,另一個使用的是 https,那么它們也屬于跨域訪問。常見的跨域問題如下圖所示:
| 場景編號 | 當(dāng)前頁面地址(發(fā)起方) | 資源地址(目標(biāo)方) | 是否跨域 | 原因說明 |
|---|---|---|---|---|
| 1 | http://example.com | http://example.com | 否 | 協(xié)議、域名、端口都相同 |
| 2 | http://example.com | https://example.com | 是 | 協(xié)議不同 |
| 3 | http://example.com | http://example.com:8080 | 是 | 端口不同 |
| 4 | http://example.com | http://sub.example.com | 是 | 子域名不同 |
| 5 | http://example.com | http://example.org | 是 | 主域名不同 |
| 6 | http://example.com | http://example.com/path/page | 否 | 僅路徑不同,不構(gòu)成跨域 |
| 7 | http://127.0.0.1 | http://localhost | 是 | 雖然都是本地,但域名不同 |
| 8 | http://localhost:3000 | http://localhost:4000 | 是 | 端口不同 |
| 9 | http://a.example.com | http://b.example.com | 是 | 子域名不同 |
| 10 | https://example.com | https://example.com | 否 | 協(xié)議、域名、端口都相同 |
跨域的核心判斷標(biāo)準(zhǔn)是:協(xié)議(scheme)、主機(jī)(host)、端口(port)三者中有任意一個不同即為跨域。
二、跨域解決方案
在Spring Boot中,可以使用CORS(跨源資源共享,Cross-Origin Resource Sharing)來解決前端請求接口時出現(xiàn)的跨域問題。Spring Boot 提供了多種方式來配置 CORS,以下是幾種常見的解決方式:
方法一:使用 @CrossOrigin 注解(適用于單個控制器或方法)
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*") // 允許所有來源跨域訪問
public class MyController {
@GetMapping("/data")
public String getData() {
return "Hello, CORS!";
}
}
你也可以只在特定方法上添加:
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("/specific")
public String specificEndpoint() {
return "This is CORS-enabled only for localhost:3000";
}
方法二:全局配置 CORS(推薦)
適合需要對整個項(xiàng)目的接口統(tǒng)一進(jìn)行跨域配置。
方法 2.1:實(shí)現(xiàn) WebMvcConfigurer
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsGlobalConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 匹配所有請求路徑
.allowedOrigins("*") // 允許所有來源
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允許的方法
.allowedHeaders("*") // 允許的請求頭
.allowCredentials(true) // 是否允許攜帶cookie
.maxAge(3600); // 預(yù)檢請求緩存時間(秒)
}
}
allowedOrigins("*") 與 allowCredentials(true) 不可同時使用,若需攜帶 Cookie,需指定具體域名。
方法三:通過 Filter 自定義 CORS 過濾器
適用于更底層的控制(不推薦,除非有特殊需求)。
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(request, response);
}
}
注意事項(xiàng)
- 如果你使用了
spring-security,還需要在安全配置類中額外開啟 CORS。 @CrossOrigin默認(rèn)支持 GET/HEAD/POST,其他請求方法如 PUT/DELETE 需要手動配置。- 在生產(chǎn)環(huán)境下,不要使用
"\*"通配符,應(yīng)明確指定允許的域名。
三、完整示例演示
寫一個完整的node.js前端出現(xiàn)要跨域訪問的時候,用SpringBoot的CORS()來解決跨域問題完整代碼實(shí)例。
3.1 創(chuàng)建前端的node.js服務(wù)
創(chuàng)建目錄
mkdir node-frontend && cd node-frontend
初始化
npm init -y
安裝依賴
npm install express node-fetch cors

新建一個index.js文件
const express = require('express');
const fetch = require('node-fetch');
const cors = require('cors');
const app = express();
const PORT = 3000;
app.use(cors()); // 允許前端頁面跨域訪問(如果需要)
// 前端頁面
app.get('/', (req, res) => {
res.send(`
<html>
<body>
<h2>Node.js Frontend</h2>
<button onclick="callBackend()">Call Spring Boot API</button>
<p id="result"></p>
<script>
function callBackend() {
fetch('http://localhost:8080/api/hello', {
method: 'GET',
credentials: 'include'
})
.then(response => response.text())
.then(data => {
document.getElementById('result').innerText = data;
})
.catch(error => console.error('Error:', error));
}
</script>
</body>
</html>
`);
});
app.listen(PORT, () => {
console.log(`Frontend running at http://localhost:${PORT}`);
});
啟動node.js的服務(wù)
cd node-frontend node index.js
訪問http://localhost:3000/,看到如下頁面

在沒有配置這個的時候,通過F12查看控制臺,點(diǎn)擊按鈕會提示如下信息:

3.2 創(chuàng)建后端的springboot服務(wù)
后端接口:HelloController.java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello from Spring Boot!";
}
}
跨域配置:CorsConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000") // 只允許 node 前端
.allowedMethods("GET", "POST", "OPTIONS", "DELETE")
.allowCredentials(true);
}
}
啟動springboot和node.js服務(wù)以后,再去訪問http://localhost:3000/,點(diǎn)擊下面這個按鈕,就會順利拿到后端返回的數(shù)據(jù)

四、CORS詳細(xì)解析
下面是對提到的 Spring Boot 跨域配置中每一項(xiàng)的詳細(xì)解釋:
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000") // 只允許來自該源的跨域請求
.allowedMethods("GET", "POST", "OPTIONS", "DELETE") // 允許的 HTTP 方法
.allowCredentials(true); // 允許攜帶憑證(如 Cookie)
逐項(xiàng)解釋
addMapping("/**")
- 作用:設(shè)置哪些 URL 路徑可以被跨域請求訪問。
"/**"表示對 所有接口 開啟跨域支持。- 示例:
/api/hello、/user/info等都受此配置控制。
allowedOrigins("http://localhost:3000")
- 作用:設(shè)置允許跨域請求的來源(origin),即前端運(yùn)行的地址。
- 瀏覽器發(fā)起跨域請求時會帶上
Origin請求頭,Spring 會檢查它是否在這個列表中。 - 示例:
- 當(dāng)前設(shè)置只允許從
http://localhost:3000發(fā)起的跨域請求。 - 如果你用的是 React/Vite/Node.js 前端開發(fā)服務(wù)器,就很可能是這個端口。
- 當(dāng)前設(shè)置只允許從
注意:如果你使用 allowedOrigins("*") 通配所有來源,就不能使用 allowCredentials(true),否則瀏覽器會拒絕響應(yīng)。
allowedMethods("GET", "POST", "OPTIONS", "DELETE")
- 作用:指定允許前端發(fā)起的 HTTP 方法。
- 常見的跨域請求方法包括:
GET:獲取資源POST:提交數(shù)據(jù)OPTIONS:預(yù)檢請求(preflight),瀏覽器用于詢問服務(wù)器是否允許跨域DELETE:刪除資源
- 你也可以加上
"PUT"、"PATCH"等方法,取決于你的 API 接口支持哪些。
allowCredentials(true)
作用:允許前端在跨域請求中攜帶認(rèn)證信息(如
Cookie、HTTP 認(rèn)證頭)。如果你希望用戶登錄后發(fā)送帶 cookie 的請求(比如
JSESSIONID),必須設(shè)置為true。配合前端的配置使用:
fetch("http://localhost:8080/api/hello", {
credentials: "include" // 必須設(shè)置這項(xiàng)才能帶上 Cookie
});
**關(guān)鍵點(diǎn):**當(dāng)
allowCredentials(true)時,allowedOrigins("*")是不允許的,必須指定明確的 Origin。
allowedHeaders("*")
- 作用:指定哪些請求頭(headers)是允許的跨域請求中使用的。
- 默認(rèn)情況下,瀏覽器不允許跨域請求攜帶自定義請求頭。使用
allowedHeaders可以明確告訴 Spring Boot 服務(wù)器,允許哪些請求頭攜帶過來。
示例:
.allowedHeaders("*") // 允許所有請求頭
這表示只有
Authorization和Content-Type這兩個頭部字段可以在跨域請求中被使用。
例子:
假設(shè)你想在請求中添加一個自定義的 X-Auth-Token 頭部字段來驗(yàn)證身份,那么你需要在服務(wù)器端配置允許這個頭部:
.allowedHeaders("X-Auth-Token")
maxAge(3600)
- 作用:指定瀏覽器在進(jìn)行 預(yù)檢請求(preflight) 時,緩存響應(yīng)的最大時間(單位:秒)。
- 預(yù)檢請求是指在實(shí)際發(fā)起跨域請求之前,瀏覽器會先發(fā)送一個
OPTIONS請求到目標(biāo)服務(wù)器,詢問是否允許跨域操作。服務(wù)器響應(yīng)該請求后,瀏覽器會根據(jù)返回的信息決定是否繼續(xù)發(fā)送實(shí)際的請求。
示例:
.maxAge(3600) // 允許預(yù)檢請求的緩存時間為 3600 秒(即 1 小時)
- 實(shí)際效果:如果預(yù)檢請求成功,瀏覽器會緩存該響應(yīng) 3600 秒,直到緩存過期才重新發(fā)送預(yù)檢請求。如果你有大量的跨域請求,增加緩存時間能夠減少預(yù)檢請求的頻繁發(fā)起,提高性能。
例子:
- 如果你經(jīng)常發(fā)送跨域請求,而預(yù)檢請求(OPTIONS)非常頻繁,你可以通過增加
maxAge來減少預(yù)檢請求的次數(shù),從而提高性能。 maxAge(3600)表示預(yù)檢請求的響應(yīng)將在 1 小時內(nèi)緩存,不會再發(fā)送新的預(yù)檢請求。
綜合配置
根據(jù)上述的解釋,完整的跨域配置代碼可能是這樣的:
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000") // 只允許來自該源的跨域請求
.allowedMethods("GET", "POST", "OPTIONS", "PUT", "DELETE") // 允許的 HTTP 方法
.allowedHeaders("Content-Type", "Authorization", "X-Auth-Token") // 允許的請求頭
.allowCredentials(true) // 允許攜帶憑證(如 Cookie)
.maxAge(3600); // 預(yù)檢請求緩存 1 小時
總結(jié)配置最佳實(shí)踐
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000") // 推薦明確指定前端地址
.allowedMethods("GET", "POST", "OPTIONS", "PUT", "DELETE")
.allowedHeaders("*") // 可選,允許前端發(fā)送的自定義 Header
.allowCredentials(true)
.maxAge(3600); // 可選,預(yù)檢請求的緩存時間(單位秒)
以上就是SpringBoot使用CORS解決無法跨域訪問問題的具體步驟的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot CORS跨域訪問的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何利用Spring的@Import擴(kuò)展點(diǎn)與spring進(jìn)行無縫整合
這篇文章主要介紹了如何利用Spring的@Import擴(kuò)展點(diǎn)與spring進(jìn)行無縫整合的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08
SpringSecurity中的UserDetails和UserDetailsService接口詳解
這篇文章主要介紹了SpringSecurity中的UserDetails和UserDetailsService接口詳解,UserDetailsService 在 Spring Security 中主要承擔(dān)查詢系統(tǒng)內(nèi)用戶、驗(yàn)證密碼、封裝用戶信息和角色權(quán)限,需要的朋友可以參考下2023-11-11
SpringBoot接口路徑重復(fù),啟動服務(wù)器失敗的解決
這篇文章主要介紹了SpringBoot接口路徑重復(fù),啟動服務(wù)器失敗的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
Java8 stream 中利用 groupingBy 進(jìn)行多字段分組求和案例
這篇文章主要介紹了Java8 stream 中利用 groupingBy 進(jìn)行多字段分組求和案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
java中l(wèi)ambda(函數(shù)式編程)一行解決foreach循環(huán)問題
這篇文章主要介紹了java中l(wèi)ambda(函數(shù)式編程)一行解決foreach循環(huán)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot整合MP通過Redis實(shí)現(xiàn)二級緩存方式
這篇文章主要介紹了SpringBoot整合MP通過Redis實(shí)現(xiàn)二級緩存方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01

