# 处理跨域
询问了 ds r1 怎么解决跨域,他给了我以下几个方法(只测试了第二种,其他的先懒得测了):
(从这里开始是 ds 说的)
在 Spring Boot 中处理跨域请求可以通过以下几种方法实现,以下是详细的配置步骤和示例:
# 方法一:使用 @CrossOrigin 注解(局部配置)
适用于对单个 Controller 或方法设置跨域规则。
步骤:
- 在 Controller 类或方法上添加 
@CrossOrigin注解
可配置允许的来源、方法、头部等。 
示例代码:
@RestController | |
@RequestMapping("/api")  | |
@CrossOrigin(origins = "http://localhost:3000",  | |
methods = {RequestMethod.GET, RequestMethod.POST},  | |
allowedHeaders = "*",  | |
allowCredentials = "true")  | |
public class MyController {  | |
@GetMapping("/data")  | |
public ResponseEntity<String> getData() {  | |
        // ... ...  | |
    } | |
} | 
参数说明:
origins: 允许的源列表(如"http://example.com")methods: 允许的 HTTP 方法(如GET,POST)allowedHeaders: 允许的请求头(默认为所有)allowCredentials: 是否允许携带凭证(如 Cookies)
# 方法二:全局配置(推荐)
通过实现 WebMvcConfigurer 接口统一配置跨域规则。
步骤:
2. 创建全局跨域配置类
使用 @Configuration 注解标记,并实现 WebMvcConfigurer 。
示例代码:
@Configuration | |
public class CorsConfig implements WebMvcConfigurer {  | |
    @Override | |
public void addCorsMappings(CorsRegistry registry) {  | |
registry.addMapping("/**") // 匹配所有路径  | |
.allowedOrigins("http://localhost:3000") // 允许的源  | |
.allowedMethods("*") // 允许所有 HTTP 方法  | |
.allowedHeaders("*") // 允许所有请求头  | |
.allowCredentials(true) // 允许携带凭证  | |
.maxAge(3600); // 预检请求缓存时间(秒)  | |
    } | |
} | 
# 方法三:结合 Spring Security 的跨域配置
如果项目使用了 Spring Security,需额外配置。
步骤:
3. 在 Security 配置中启用 CORS 并禁用 CSRF(如需携带凭证需开启)
4. 确保全局 CORS 配置生效。
示例代码:
@Configuration | |
@EnableWebSecurity | |
public class SecurityConfig extends WebSecurityConfigurerAdapter {  | |
    @Override | |
protected void configure(HttpSecurity http) throws Exception {  | |
http.cors().and() // 启用 CORS 支持  | |
.csrf().disable() // (可选)关闭 CSRF 保护  | |
.authorizeRequests()  | |
.anyRequest().authenticated();  | |
    } | |
    // 若使用全局 CORS 配置,需显式声明 CorsConfigurationSource | |
    @Bean | |
public CorsConfigurationSource corsConfigurationSource() {  | |
CorsConfiguration config = new CorsConfiguration();  | |
config.setAllowedOrigins(Arrays.asList("http://localhost:3000"));  | |
config.setAllowedMethods(Arrays.asList("GET", "POST"));  | |
config.setAllowedHeaders(Arrays.asList("*"));  | |
config.setAllowCredentials(true);  | |
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();  | |
source.registerCorsConfiguration("/**", config);  | |
return source;  | |
    } | |
} | 
# 方法四:使用 Filter 手动配置
指定一个 Filter 来设置响应头,灵活但需谨慎。
步骤:
5. 创建 CORS 过滤器并注册
手动设置响应头处理跨域。
示例代码:
@WebFilter("/*")  | |
public class CorsFilter implements Filter {  | |
    @Override | |
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)  | |
throws IOException, ServletException {  | |
HttpServletResponse response = (HttpServletResponse) res;  | |
response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");  | |
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");  | |
response.setHeader("Access-Control-Allow-Headers", "*");  | |
response.setHeader("Access-Control-Allow-Credentials", "true");  | |
response.setHeader("Access-Control-Max-Age", "3600");  | |
chain.doFilter(req, res);  | |
    } | |
} | 
注册 Filter:
@Configuration | |
public class FilterConfig {  | |
    @Bean | |
public FilterRegistrationBean<CorsFilter> corsFilter() {  | |
FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>();  | |
registration.setFilter(new CorsFilter());  | |
registration.addUrlPatterns("/*");  | |
return registration;  | |
    } | |
} | 
# 常见问题解决
- 预检请求(OPTIONS)被拦截
- 确保 Spring Security 放行 OPTIONS 方法:
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();
 
 - 确保 Spring Security 放行 OPTIONS 方法:
 allowCredentials=true但allowedOrigins包含通配符*- 需指定具体域名如 
.allowedOrigins("http://localhost:3000")。 
- 需指定具体域名如 
 
# 最佳实践建议
- 开发环境:允许所有来源( 
allowedOrigins("*")),快速调试。 - 生产环境:精确配置 
allowedOrigins以增强安全性。 - 结合全局配置和 Spring Security:确保多层级安全控制。
 - 日志与测试:使用 Postman 或浏览器开发者工具验证响应头是否正确包含 CORS 信息。
 
按需选择配置方式,推荐使用 全局配置(方法二) 搭配 Spring Security(方法三),既统一管理,又兼顾安全性。
(ds 说的结束)
# 多路径放行
测试了第二个方法,发现 ds 给我的代码只能指定 ip 及端口号处理跨域。以前我 midway 直接配置一下就全都放行了。当然,指定路径肯定更安全。
尝试直接把放行路径改成 * ,出了问题,故问通义灵码,以下是回答:
从错误信息来看,问题出在 CORS(跨域资源共享)配置上。具体来说,当 allowCredentials 设置为 true 时, allowedOrigins 不能包含通配符 * ,因为这会导致 Access-Control-Allow-Origin 响应头无法正确设置。要解决这个问题,有两种方法:
- 显式列出允许的源:将具体的域名添加到 
allowedOrigins中。 - 使用 
allowedOriginPatterns:这是 Spring 5.3 引入的新特性,允许你使用模式来匹配多个源。
下面是具体的代码示例,展示了如何进行这两种配置: 
# 方法一:显式列出允许的源
import org.springframework.context.annotation.Bean;  | |
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 WebConfig implements WebMvcConfigurer {  | |
    @Override | |
public void addCorsMappings(CorsRegistry registry) {  | |
registry.addMapping("/**")  | |
.allowedOrigins("https://example.com", "https://another-example.com") // 显式列出允许的源  | |
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")  | |
.allowCredentials(true);  | |
    } | |
} | 
# 方法二:使用 allowedOriginPatterns
import org.springframework.context.annotation.Bean;  | |
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 WebConfig implements WebMvcConfigurer {  | |
    @Override | |
public void addCorsMappings(CorsRegistry registry) {  | |
registry.addMapping("/**")  | |
.allowedOriginPatterns("https://*.example.com", "https://*.another-example.com") // 使用模式匹配多个源  | |
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")  | |
.allowCredentials(true);  | |
    } | |
} | 
# 解释
allowedOrigins:用于指定允许的源域名。如果需要支持多个域名,可以逐一列出。allowedOriginPatterns:用于指定允许的源域名模式。这种方式更加灵活,适用于多个子域名或特定模式的域名。allowCredentials(true):允许凭证(如 Cookie、HTTP 认证信息等)随请求发送。
选择其中一种方法进行配置即可解决问题。推荐使用allowedOriginPatterns,因为它更灵活且易于维护。
# 放行 localhost
又问了一下怎么可以放行全部 localhost,通义灵码给了回答:
如果你想要允许所有来自 localhost 的源,可以使用通配符 * 来匹配所有端口。但是需要注意的是,使用 * 允许所有源时, allowCredentials(true) 是不允许的,因为这会引发安全问题。
如果你确实需要允许所有 localhost 的源并且允许携带凭证,你需要明确指定每个可能的端口,或者在开发环境中暂时放宽限制。以下是两种方法:
指定所有可能的
localhost端口:@Overridepublic void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000", "http://localhost:8080", "http://localhost:8081") // 添加所有可能的端口
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}在开发环境中允许所有源(不推荐用于生产环境):
@Overridepublic void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*") // 允许所有源
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(false) // 不允许携带凭证
.maxAge(3600);
}