Java注解篇:@CrossOrigin
前言
在现代前后端分离的开发模式中,跨域请求(CORS)成为了不可避免的问题。浏览器的同源策略限制了不同源之间的请求交互,而 Spring Framework 为了解决这一问题,引入了 @CrossOrigin
注解。
@CrossOrigin
是 Spring 4.2 引入的注解,允许我们在控制器或具体方法上启用跨域请求支持。它是实现 CORS 的便捷方式。
本文将详细介绍 @CrossOrigin
的使用方法、注解参数、实际场景中的应用示例,以及其底层实现原理,帮助你全面理解并灵活使用该注解。
一、跨域基础知识
1. 什么是跨域
跨域是指浏览器不能执行其他域下的脚本。一个域名下的网页去请求另一个域名下的资源,就构成了跨域。常见的跨域情况包括:
-
协议不同(http vs https)
-
域名不同(example.com vs api.example.com)
-
端口不同(example.com:8080 vs example.com:8081)
2. 浏览器的同源策略
同源策略(Same-Origin Policy)是浏览器的一个安全功能,它阻止一个源的 JavaScript 脚本去访问另一个源的内容。
3. CORS(跨源资源共享)
CORS 是一种机制,它通过设置响应头来告诉浏览器:当前资源允许哪些域名访问,从而实现跨源访问。
常见的响应头包括:
-
Access-Control-Allow-Origin
-
Access-Control-Allow-Methods
-
Access-Control-Allow-Headers
-
Access-Control-Allow-Credentials
二、@CrossOrigin 注解使用
1. 基本使用
在控制器类上添加 @CrossOrigin
:
@CrossOrigin
@RestController
@RequestMapping("/api")
public class MyController {@GetMapping("/data")public String getData() {return "跨域数据";}
}
这将允许所有源对 /api/data
进行访问。
2. 作用范围
-
类级别:对控制器中所有方法生效。
-
方法级别:只对该方法生效,优先级高于类级别注解。
@RestController
@RequestMapping("/api")
public class MyController {@CrossOrigin(origins = "http://example.com")@GetMapping("/open")public String openAccess() {return "example.com 可访问";}@GetMapping("/restricted")public String restrictedAccess() {return "无跨域支持";}
}
3. 常用参数
属性 | 描述 |
---|---|
origins | 允许哪些来源访问,默认允许所有(*) |
methods | 允许的 HTTP 方法(如 GET、POST) |
allowedHeaders | 允许的请求头 |
exposedHeaders | 响应中暴露的头信息 |
allowCredentials | 是否允许携带 Cookie(默认为 false) |
maxAge | 预检请求的缓存时间(单位:秒) |
示例
@CrossOrigin(origins = "http://localhost:3000",methods = {RequestMethod.GET, RequestMethod.POST},allowedHeaders = {"Content-Type", "Authorization"},allowCredentials = "true",maxAge = 3600
)
@GetMapping("/secure-data")
public String secureData() {return "安全数据";
}
三、全局跨域配置
除了使用 @CrossOrigin
注解,我们也可以通过配置类来设置全局跨域策略:
@Configuration
public class CorsGlobalConfiguration implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("http://localhost:3000").allowedMethods("GET", "POST", "PUT", "DELETE").allowCredentials(true).maxAge(3600);}
}
全局配置可以替代注解形式,适用于统一配置策略的项目。
四、实现原理分析
1. 注解处理入口
@CrossOrigin
是通过 Spring MVC 的处理器拦截器和过滤器链处理的,其底层依赖 CorsProcessor
。
在 DispatcherServlet
初始化过程中,会将 HandlerMapping
和 HandlerAdapter
组合成执行链,而跨域处理通过注册 CorsInterceptor
实现。
2. 核心组件
CorsFilter
CorsFilter
是 Spring Web 提供的过滤器,用于处理所有请求的 CORS 校验。
public class CorsFilter extends OncePerRequestFilter {private final CorsConfigurationSource configSource;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {CorsConfiguration corsConfig = this.configSource.getCorsConfiguration(request);CorsProcessor processor = new DefaultCorsProcessor();processor.processRequest(corsConfig, request, response);}
}
DefaultCorsProcessor
该类负责核心的跨域逻辑,包括解析请求头、设置响应头等。
public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request, HttpServletResponse response) {if (!this.isCorsRequest(request)) {return true;}// 校验 Origin、方法、头部等// 设置 Access-Control-* 响应头return true;
}
3. 与注解的结合
当控制器或方法上有 @CrossOrigin
注解时,Spring 会自动解析注解配置并生成 CorsConfiguration
对象,注入到请求的上下文中,最终由 CorsFilter
应用。
五、注意事项
-
allowCredentials = true
时,allowedOrigins
不能为*
,否则浏览器会拦截。 -
浏览器对
OPTIONS
请求是自动发出的“预检请求”,务必允许该方法。 -
不同浏览器对 CORS 处理略有差异,需进行充分测试。
-
建议跨域配置集中管理,避免分散在多个注解中。
六、常见问题与排查
问题 1:浏览器提示 CORS 错误
-
检查响应中是否包含
Access-Control-Allow-Origin
-
确认服务器是否允许对应的方法与头信息
-
检查是否为预检请求被拒绝
问题 2:Cookie 无法携带
-
需设置
allowCredentials = true
-
客户端必须设置
xhr.withCredentials = true
-
不能使用
*
通配源
七、总结
@CrossOrigin
是一个简单但非常实用的注解,极大简化了跨域配置,特别适合前后端分离架构下的 API 接口服务。
通过结合全局配置和方法级注解,我们可以灵活控制不同接口的访问策略,从而兼顾安全性与开发便利。掌握 @CrossOrigin
的使用和底层原理,是现代 Spring Boot 开发者的基本功之一。