Spring中CORS的ORIGIN含义、配置及跨域机制技术问询
1. 什么是ORIGIN?
在Web开发里,ORIGIN(源)指的是一个请求的来源地址,由协议、域名、端口三者共同组成。比如:
http://localhost:8080是一个完整的源(协议http,域名localhost,端口8080)https://www.example.com是另一个源(协议https,域名www.example.com,默认端口443可省略)
只要这三者中有一个不同,就属于不同的源——这是浏览器同源策略的核心判断依据。
2. ORIGIN在Spring框架中的意义
Spring作为后端框架,处理跨域请求时会基于请求的ORIGIN来判断是否允许该请求访问后端资源。简单来说,Spring需要明确哪些来源的前端请求是被信任的,从而决定是否返回合法响应,避免恶意网站随意调用你的API接口。
3. @CrossOrigin注解的origins属性怎么设置?
@CrossOrigin是Spring提供的用来开启跨域支持的注解,其中origins属性用来指定允许访问当前控制器/方法的源列表。
常见设置场景:
- 允许单个特定源:就像你示例里的
origins = "http://domain2.com",表示只接受来自http://domain2.com的跨域请求。 - 允许多个特定源:用数组形式,比如
origins = {"http://domain2.com", "https://app.example.com"} - 允许所有源:直接设为
origins = "*"(注意:生产环境不建议这么做,会有安全风险,仅适合开发测试阶段) - 允许本地开发源:比如
origins = "http://localhost:3000"(前端React/Vue项目常用的本地端口)
你提供的示例代码可以更清晰地解读:
// 指定只允许http://domain2.com的跨域请求,maxAge=3600表示预检请求的缓存时长(秒) @CrossOrigin(origins = "http://domain2.com", maxAge = 3600) @RestController @RequestMapping("/account") public class AccountController { @GetMapping("/{id}") public Account retrieve(@PathVariable Long id) { // 业务逻辑:根据ID查询账户信息 } @DeleteMapping("/{id}") public void remove(@PathVariable Long id) { // 业务逻辑:根据ID删除账户 } }
4. 示例中的"http://domain2.com"代表什么?
这个地址就是被允许发起跨域请求的前端源地址。假设你的后端服务部署在http://domain1.com,而前端页面部署在http://domain2.com,当前端页面调用后端的/account接口时,就属于跨域请求——此时后端通过@CrossOrigin(origins = "http://domain2.com")明确允许这个源的请求访问。
5. CORS在服务端和客户端的运行机制
CORS(跨域资源共享)是浏览器和服务端共同遵守的一套安全规则,用来合法实现跨域请求,分为两种请求类型:
简单请求(需满足所有条件):
- 请求方法为GET、HEAD、POST三者之一
- 请求头仅包含Accept、Accept-Language、Content-Language、Content-Type(值限定为application/x-www-form-urlencoded、multipart/form-data、text/plain)
运行流程:
- 前端浏览器直接发送请求,自动在请求头带上
Origin字段,值为当前页面的源 - 服务端收到请求后,检查
Origin是否在允许列表内 - 如果允许,服务端响应头会返回
Access-Control-Allow-Origin字段(值为对应源或*),浏览器收到后允许前端获取响应;如果不允许,浏览器会拦截响应,前端无法拿到数据
预检请求(非简单请求,比如PUT/DELETE方法、自定义请求头等):
- 浏览器先发送OPTIONS类型的预检请求,询问服务端:“我接下来要发一个XX方法的请求,你允许吗?”,请求头包含
Origin、Access-Control-Request-Method(待发送的请求方法)、Access-Control-Request-Headers(自定义请求头) - 服务端收到预检请求后,检查
Origin、请求方法、请求头是否都在允许范围内,返回响应时会带上Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers等字段,maxAge字段用来指定预检请求的缓存时长(比如你示例里的3600秒,意味着1小时内不用重复发送预检请求) - 如果预检通过,浏览器才会发送真正的业务请求;如果不通过,浏览器直接拦截,不会发送后续请求
6. 关于银行账户示例的理解
这个示例是用来解释同源策略和CORS必要性的经典场景:
假设你登录了网上银行(源为https://bank.com),银行页面保存了你的登录凭证(比如Cookie)。如果没有同源策略和CORS限制,恶意网站(https://evil.com)可以直接发起请求到https://bank.com/api/transfer,带上你的Cookie,偷偷转走你的资金——这显然是极度危险的。
而有了同源策略后,浏览器会拦截https://evil.com发起的跨域请求;如果银行的后端需要允许某些可信的源(比如自己的移动端Web页面https://m.bank.com)访问API,就可以通过CORS配置(比如Spring的@CrossOrigin)指定允许的源,既保证安全,又支持合法的跨域需求。
内容的提问来源于stack exchange,提问作者ekka

