如何在 Spring MVC 中实现跨域资源共享(CORS)?
跨域资源共享(Cross-Origin Resource Sharing, CORS)是一种机制,它使用额外的HTTP头来告诉浏览器让运行在一个源(domain)上的Web应用被准许访问来自不同源服务器上的指定资源。
题目详细答案
使用 @CrossOrigin
注解
@CrossOrigin
是 Spring Framework 提供的一个注解,用于在控制器方法或整个控制器上指定允许的跨域请求。这个注解可以在方法级别或类级别使用。
@RestController
public class MyController {
@GetMapping("/api/data")
@CrossOrigin(origins = "http://localhost:3000", maxAge = 3600)
public List<Data> getData() {
// 返回数据
}
}
@CrossOrigin
注解指定了来自 http://localhost:3000
的跨域请求是被允许的,并且设置了预检请求的缓存时间为 3600 秒(1 小时)。
@RestController
@CrossOrigin(origins = "http://localhost:3000", maxAge = 3600)
public class MyController {
@GetMapping("/api/data")
public List<Data> getData() {
// 返回数据
}
}
所有在 MyController
中的方法都将允许来自 http://localhost:3000
的跨域请求。
使用 WebMvcConfigurer
接口
如果你需要在全局范围内配置 CORS 策略,可以实现 WebMvcConfigurer
接口并重写 addCorsMappings
方法。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000")
.maxAge(3600);
}
}
创建一个 CorsConfig
类,实现了 WebMvcConfigurer
接口,并在 addCorsMappings
方法中添加了一个全局的 CORS 配置,允许来自 http://localhost:3000
的跨域请求。
Spring MVC 跨域(CORS)配置详解
跨域资源共享(CORS)概述
跨域资源共享(Cross-Origin Resource Sharing, CORS)是一种机制,它使用额外的HTTP头来告诉浏览器让运行在一个源(domain)上的Web应用被准许访问来自不同源服务器上的指定资源。
两种配置方式对比
特性 |
@CrossOrigin 注解 |
WebMvcConfigurer 接口 |
作用范围 |
方法级/类级 |
全局配置 |
灵活性 |
细粒度控制 |
统一管理 |
适用场景 |
特定端点需要特殊CORS规则 |
整个应用使用相同的CORS策略 |
维护性 |
分散在各处 |
集中管理 |
优先级 |
更具体(方法>类>全局) |
基础配置 |
@CrossOrigin 注解详解
基本用法
@RestController
@RequestMapping("/api")
public class MyController {
// 方法级别配置
@GetMapping("/data")
@CrossOrigin(origins = "http://localhost:3000")
public ResponseEntity<List<Data>> getData() {
// 业务逻辑
}
// 类级别配置
@CrossOrigin(origins = "https://example.com", maxAge = 1800)
@GetMapping("/users")
public ResponseEntity<List<User>> getUsers() {
// 业务逻辑
}
}
注解参数说明
参数名 |
类型 |
说明 |
origins |
String[] |
允许的源列表,默认"*" |
allowedHeaders |
String[] |
允许的请求头,默认"*" |
exposedHeaders |
String[] |
暴露给客户端的响应头 |
methods |
RequestMethod[] |
允许的HTTP方法,默认与注解的方法匹配 |
allowCredentials |
boolean |
是否允许发送凭据(cookies等),默认false |
maxAge |
long |
预检请求缓存时间(秒),默认1800 |
高级用法示例
// 允许多个源
@CrossOrigin(origins = {"http://localhost:3000", "https://example.com"})
// 允许所有源但限制方法
@CrossOrigin(origins = "*", methods = {RequestMethod.GET, RequestMethod.POST})
// 允许凭据和自定义头
@CrossOrigin(
origins = "https://app.example.com",
allowedHeaders = {"Authorization", "Content-Type"},
exposedHeaders = {"X-Custom-Header"},
allowCredentials = "true",
maxAge = 3600
)
WebMvcConfigurer 全局配置详解
基本配置
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000", "https://example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true)
.maxAge(3600);
}
}
配置选项说明
方法名 |
说明 |
addMapping(String) |
设置CORS映射路径,支持Ant风格路径模式 |
allowedOrigins |
设置允许的来源,可以多个 |
allowedMethods |
设置允许的HTTP方法 |
allowedHeaders |
设置允许的请求头 |
exposedHeaders |
设置暴露给客户端的响应头 |
allowCredentials |
设置是否允许凭据 |
maxAge |
设置预检请求缓存时间 |
多路径不同规则配置
@Override
public void addCorsMappings(CorsRegistry registry) {
// API路径配置
registry.addMapping("/api/**")
.allowedOrigins("https://api-consumer.com")
.allowedMethods("GET", "POST");
// 管理后台配置
registry.addMapping("/admin/**")
.allowedOrigins("https://admin.example.com")
.allowedMethods("*")
.allowCredentials(true);
// 公共API配置
registry.addMapping("/public/**")
.allowedOrigins("*")
.allowedMethods("GET");
}
最佳实践建议
- 安全考虑:
-
- 避免在生产环境使用
allowedOrigins("*")
- 明确指定允许的来源列表
- 对于敏感操作,设置
allowCredentials(false)
- 避免在生产环境使用
- 性能优化:
-
- 合理设置
maxAge
减少预检请求 - 按需暴露头信息,避免不必要的
exposedHeaders
- 合理设置
- 混合使用策略:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 全局基础配置
registry.addMapping("/**")
.allowedOrigins("https://main-site.com")
.maxAge(1800);
}
}
@RestController
@CrossOrigin(origins = "https://partner-site.com") // 特定控制器覆盖配置
@RequestMapping("/partner-api")
public class PartnerApiController {
// ...
}
- 常见问题解决:
-
- 配置不生效:检查配置类是否被正确扫描,注解是否放在正确位置
- 预检请求失败:确保OPTIONS方法被允许,maxAge设置合理
- 凭据问题:当使用
allowCredentials(true)
时,不能使用allowedOrigins("*")
- Spring Security集成:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and() // 启用Spring Security的CORS支持
.csrf().disable()
// 其他安全配置...
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://trusted.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
实际应用场景
- 前后端分离项目:
@CrossOrigin(origins = "http://localhost:8080")
@RestController
public class FrontendApiController {
// 前端专用API
}
- 微服务间调用:
@Configuration
public class InternalCorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/internal/**")
.allowedOrigins("https://service1.example.com", "https://service2.example.com")
.allowedHeaders("*")
.allowCredentials(true);
}
}
- 公共API:
@CrossOrigin(origins = "*", methods = RequestMethod.GET)
@RestController
@RequestMapping("/public-api")
public class PublicApiController {
// 开放给第三方使用的API
}
根据项目需求选择合适的配置方式,通常建议在大型项目中使用全局配置结合局部注解的方式,既能保证统一的策略,又能满足特殊端点的需求。
更多推荐
所有评论(0)