一文盤點(diǎn)SpringBoot中常用跨域處理方案
1.什么是跨域
跨域是瀏覽器為了保障安全而遵循的一種規(guī)則,是同源策略的一部分。
- 同源:要求協(xié)議、域名、端口三者完全相同。
- 跨域:只要協(xié)議、域名、端口中有任何一個(gè)不同,瀏覽器就會(huì)判定為跨域請(qǐng)求。
跨域(Cross-Origin)是瀏覽器獨(dú)有的安全策略,不存在于安卓、iOS、Node.js、Python、Java 等原生客戶端或服務(wù)器端環(huán)境中。因?yàn)闉g覽器是一個(gè)開(kāi)放的、執(zhí)行不可信代碼,也就是各個(gè)網(wǎng)站的 js 腳本的環(huán)境,同源策略是為了保證用戶的信息安全。
所以,如果平時(shí)測(cè)試接口用的是 postman 發(fā)送請(qǐng)求,不需要關(guān)心跨域問(wèn)題,但是如果是前后端聯(lián)調(diào)就必須處理跨域問(wèn)題。
2.瀏覽器處理跨域請(qǐng)求的方式
瀏覽器遵循同源策略,不允許頁(yè)面獲取跨域請(qǐng)求返回的響應(yīng)結(jié)果。
比如:當(dāng)前網(wǎng)頁(yè)是 http://127.0.0.1:63342,然后向服務(wù)器 http://127.0.0.1:8080 發(fā)送 GET 請(qǐng)求獲取數(shù)據(jù)。整個(gè)過(guò)程分成三步:
- 瀏覽器發(fā)送請(qǐng)求
- 服務(wù)器接收請(qǐng)求,處理業(yè)務(wù),返回響應(yīng)
- 瀏覽器獲取服務(wù)器返回的響應(yīng)并根據(jù)響應(yīng)渲染頁(yè)面
無(wú)論是跨域請(qǐng)求還是非跨域請(qǐng)求,瀏覽器都可以發(fā)送給服務(wù)器,并且接收服務(wù)器返回的響應(yīng)數(shù)據(jù)。
- 如果該請(qǐng)求是非跨域請(qǐng)求,則 js 腳本可以訪問(wèn)響應(yīng)數(shù)據(jù)
- 如果該請(qǐng)求是跨域請(qǐng)求,瀏覽器會(huì)攔截響應(yīng)數(shù)據(jù),不讓 js 訪問(wèn)這些數(shù)據(jù)
其實(shí)瀏覽器可以向不同的域名發(fā)送請(qǐng)求,但是瀏覽器會(huì)攔截響應(yīng)內(nèi)容,不讓 js 訪問(wèn),無(wú)論請(qǐng)求是否成功。
3.跨域處理方案
跨域處理的核心:讓瀏覽器不要攔截跨域請(qǐng)求返回的數(shù)據(jù)。
服務(wù)器的響應(yīng)中如果有 Access-Control-Allow-Origin: * 這個(gè)響應(yīng)頭,就是告訴瀏覽器:"我是服務(wù)器,雖然我跟這個(gè)網(wǎng)頁(yè)不是同源的,但是我允許這個(gè)網(wǎng)頁(yè)跟我通信,我們之間的通信是安全的",瀏覽器就不會(huì)攔截 js 對(duì)響應(yīng)數(shù)據(jù)的訪問(wèn)。
瀏覽器發(fā)送的請(qǐng)求可以分為簡(jiǎn)單請(qǐng)求和復(fù)雜請(qǐng)求:
- 如果是簡(jiǎn)單請(qǐng)求,則瀏覽器直接發(fā)送。
- 如果是復(fù)雜請(qǐng)求,則瀏覽器先發(fā)送一個(gè)預(yù)檢請(qǐng)求,即 OPTIONS 請(qǐng)求,問(wèn)一句:"我可以發(fā)送一個(gè)超級(jí)復(fù)雜的跨域請(qǐng)求嗎?",服務(wù)器需要返回針對(duì) OPTIONS 的響應(yīng)。如果服務(wù)器允許發(fā)送這個(gè)復(fù)雜請(qǐng)求,瀏覽器才會(huì)真正發(fā)送請(qǐng)求。
常見(jiàn)的跨域處理方案有:代理服務(wù)器、后端服務(wù)器跨域配置。
3.1代理服務(wù)器
瀏覽器將請(qǐng)求發(fā)送到跟頁(yè)面同源的代理服務(wù)器,代理服務(wù)器再將請(qǐng)求轉(zhuǎn)發(fā)到目標(biāo)服務(wù)器。因?yàn)榉?wù)器間通信不受同源策略限制。比如常見(jiàn)的用 nginx 作為代理服務(wù)器。
請(qǐng)求處理過(guò)程:
- 前端發(fā)送請(qǐng)求,請(qǐng)求經(jīng)過(guò) nginx,請(qǐng)求被轉(zhuǎn)發(fā)到后端服務(wù)器。
- 服務(wù)器返回原始響應(yīng),原始響應(yīng)經(jīng)過(guò) nginx,nginx 自動(dòng)添加 Access-Control-Allow-Origin: * 響應(yīng)頭,響應(yīng)返回給前端,js 可以訪問(wèn)響應(yīng)數(shù)據(jù)。
# nginx.conf
server {
listen 63342;
# 前端頁(yè)面的域名或ip
server_name 127.0.0.1;
# 代理所有以 /api/ 開(kāi)頭的請(qǐng)求到后端服務(wù)器
location /api/ {
# 后端服務(wù)器地址
proxy_pass http://127.0.0.1:8080/;
# 修改請(qǐng)求頭,確保后端能收到正確的原始主機(jī)信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 添加CORS響應(yīng)頭,允許所有來(lái)源的請(qǐng)求,生產(chǎn)環(huán)境應(yīng)關(guān)閉
add_header 'Access-Control-Allow-Origin' '*';
# 允許的請(qǐng)求方法
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE, PATCH';
if ($request_method = 'OPTIONS') {
# 對(duì)于OPTIONS請(qǐng)求,直接返回204狀態(tài)碼,不需要轉(zhuǎn)發(fā)到后端
return 204;
}
}
}
3.2 后端跨域配置
3.2.1 配置 CORS
配置全局 CORS 規(guī)則,在所有響應(yīng)頭都配置可以跨域訪問(wèn)。
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 WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允許所有接口跨域
.allowCredentials(true) // 允許瀏覽器在跨域請(qǐng)求中發(fā)送認(rèn)證信息
.allowedOriginPatterns("*") // 允許訪問(wèn)資源的源(協(xié)議、域名、端口)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允許的方法
.allowedHeaders("*") // 允許的請(qǐng)求頭
.exposedHeaders("*"); // 哪些響應(yīng)頭可以暴露給前端js
}
}
3.2.2 提供 CorsFilter
提供一個(gè) CorsFilter 的 Bean 作為過(guò)濾器。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class MyCorsFilter {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*"); // 放行所有域名,生產(chǎn)環(huán)境請(qǐng)對(duì)此進(jìn)行修改
config.setAllowCredentials(true); // 是否發(fā)送cookie
config.addAllowedMethod("*"); // 放行的請(qǐng)求方式
config.addAllowedHeader("*"); // 放行的請(qǐng)求頭
config.addExposedHeader("*"); // 暴露頭部信息
// UrlBasedCorsConfigurationSource: 可以為不同的URL路徑設(shè)置不同的CORS規(guī)則
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
// 所有的URL路徑都使用同一個(gè)CORS規(guī)則
corsConfigurationSource.registerCorsConfiguration("/**", config);
return new CorsFilter(corsConfigurationSource);
}
}
3.2.3 @CrossOrigin 注解
在接口類上或者接口方法上添加 @CrossOrigin 注解,表示整個(gè)類、單個(gè)接口的響應(yīng)不會(huì)被攔截。
@RestController
@CrossOrigin
public class DemoController {
@PutMapping("/put")
public Integer put(MultipartFile file) {
System.out.println(file.getOriginalFilename());
return 200;
}
@GetMapping("/get")
public Integer get() {
return 200;
}
}
到此這篇關(guān)于一文盤點(diǎn)SpringBoot中常用跨域處理方案的文章就介紹到這了,更多相關(guān)SpringBoot跨域處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
idea install 時(shí)提示jdk的某個(gè)jar包的包不存在的問(wèn)題
這篇文章主要介紹了idea install 時(shí)提示jdk的某個(gè)jar包的包不存在的問(wèn)題,本文給大家分享解決方法,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
SpringAI?Agent開(kāi)發(fā)秘籍如何讓javaer也可以用上Agent?Skills
文章介紹了如何使用SpringA和Skills構(gòu)建一個(gè)代碼評(píng)審應(yīng)用,通過(guò)實(shí)戰(zhàn)示例展示如何利用SpringAI和大模型實(shí)現(xiàn)零配置的代碼評(píng)審功能,感興趣的朋友跟隨小編一起看看吧2026-04-04
SpringBoot動(dòng)態(tài)修改配置的十種方法
在SpringBoot應(yīng)用中,配置信息通常通過(guò)application.properties或application.yml文件靜態(tài)定義,應(yīng)用啟動(dòng)后這些配置就固定下來(lái)了,但我們常常需要在不重啟應(yīng)用的情況下動(dòng)態(tài)修改配置,本文將介紹SpringBoot中10種實(shí)現(xiàn)配置動(dòng)態(tài)修改的方法,需要的朋友可以參考下2025-05-05
Java判斷中英文符號(hào)、標(biāo)點(diǎn)的實(shí)現(xiàn)
本篇文章主要介紹了Java判斷中英文符號(hào)、標(biāo)點(diǎn)的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
使用Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的定時(shí)器
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的延時(shí)/定時(shí)器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-12-12
Java設(shè)計(jì)模式之命令模式詳細(xì)解析
這篇文章主要介紹了Java設(shè)計(jì)模式之命令模式詳細(xì)解析,命令模式將請(qǐng)求封裝成對(duì)象,以便使用不同的請(qǐng)求、隊(duì)列或者日志來(lái)參數(shù)化其他對(duì)象,同時(shí)也支持可撤銷的操作,需要的朋友可以參考下2024-01-01

