什么是CORS

本文详细介绍了CORS(跨源资源共享)的概念及其工作原理。包括Origin的定义、Same-Origin Security Policy的安全策略、CORS的基本流程和服务端处理方式等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

英文原文来自我的GitHub页面

CORS = Cross-Origin Resource Sharing

什么是 Origin

要理解CORS,首先得理解什么是 “Origin”。参见RFC6454:如果两个URI拥有相同的schema,host和port,我们就认为他们是来自于相同的Origin。以下是一个完整的URI的定义:

    scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]

Same-Origin Security Policy

Same-origin security policy 是对客户端的要求。在这个要求之下,网络浏览器 对来自于相同Origin的脚本允许网页间相互访问。

这里有一个违反这个约定而造成的风险Wikipedia:

Assume that a user is visiting a banking website and doesn’t log out. Then, the user goes to another site that has some malicious JavaScript code running in the background that requests data from the banking site. Because the user is still logged in on the banking site, the malicious code could do anything the user could do on the banking site. For example, it could get a list of the user’s last transactions, create a new transaction, etc. This is because the browser can send and receive session cookies to the banking site based on the domain of the banking site.

Cross-Origin Resource Sharing

CORS是一种协议,它用来约定服务端和客户端那些行为是被服务端允许的。尽管服务端是可以进行验证和认证的,但基本上这是由客户端浏览器来保证的。这些对行为的允许是放在应答包的header里面的。

工作原理

CORS的实现主要包括一些客户端的工作以及两类服务端的处理,基本流程如下图所示:
Basic Workflow

客户端

下图来自 Wikipedia Click here to visit Wikipedia
Client Workflow

服务端 (简单 CORS 请求)
前提

只对满足以下所有条件的HTTP请求做出相应的CORS回应:
1. HTTP 方法仅限于 GET, POSTHEAD.
2. 客户端清秀需要含有 Origin 头.
3. 如果客户端请求是 POST,头部 Content-Type 只可以是 application/x-www-form-urlencoded, multipart/form-data, 或 text/plain.

业务逻辑

如果origin被服务端允许,服务端返回请求是带有 Access-Controll-Allow-Origin 头, 并且这个头部信息的值和客户端Origin 的值保持一致;否则就表示不被允许。如果 Access-Controll-Allow-Origin 被设置成 "*",则意味着任何Origin都被允许。

注意:如果所访问的资源需要凭证,那么 Access-Controll-Allow-Origin 则不应该被设置为 "*" 而且 Access-Control-Allow-Credentials 头需要被设置成 true.

示例

客户端HTTP 请求

GET /api/version HTTP/1.1
User-Agent: Fiddler
Accept: application/json
Origin: http://foo.origin

服务端回应

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Date: Wed, 31 Nov 2100 19:42:00 GMT
Server: Apache-Coyote/1.1
Content-Length: 53
Connection: keep-alive
Access-Control-Allow-Origin: http://foo.origin

[response payload]
服务端(预备请求)
前提

对满足任意以下条件之一的HTTP请求做出回应:
1. HTTP请求不是 GET, POSTHEAD.
2. 客户端请求带有自定义头部
3. 如果客户端请求是 POST, 头部 Content-Type 不是 application/x-www-form-urlencoded, multipart/form-data, or text/plain.

客户端进一步请求

客户端浏览器需要进行额外的 OPTIONS 请求,并且使用以下头部信息来向服务端问询相应的HTTP方法是否被允许:
1. Origin: Javascript的Origin
2. Access-Control-Request-Method: 准备使用的 HTTP 方法
3. Access-Control-Request-Headers: 将要在上述HTTP方法中使用的自定义头部

业务逻辑

如果请求不被允许,服务端返回4XX错误。
如果请求被允许,服务端返回200并在头部包含以下信息:
1. Access-Control-Allow-Origin: 被允许的Origin。如果Origin是个列表,则每个Origin之间用 "," 隔开。
2. Access-Control-Allow-Methods: 被允许的HTTP方法,如果是多个,用 "," 隔开。
3. Access-Control-Max-Age: 一个整数,用来表达这个预备请求什么时候过期,单位是
4. Access-Control-Allow-Credentials: 可选,如果所访问资源需要凭证,这个头部需要被设置成 true

示例

客户端HTTP请求

OPTIONS /resources/31415926
User-Agent: Fiddler
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: http://foo.origin

服务端回应

HTTP/1.1 200 OK
Date: Wed, 20 Nov 2013 19:36:00 GMT
Server: Apache-Coyote/1.1
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: http://foo.client.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 50000

参考文献

### CORS定义 CORS 是 Cross-Origin Resource Sharing(跨域资源共享)的缩写,是一种基于 HTTP 头部的安全机制,用于解决不同源之间的资源访问问题。它允许浏览器中的脚本安全地从一个源加载资源到另一个源[^1]。 具体来说,CORS 提供了一种标准化的方式,使得服务器能够明确告诉客户端哪些外部来源可以访问其资源。这种机制通过在 HTTP 响应中加入特定的头部字段来实现,例如 `Access-Control-Allow-Origin` 表示允许哪个源访问资源[^1]。 --- ### CORS的工作原理 #### 1. **同源策略** 为了防止恶意网通过 JavaScript 访问其他点的内容,浏览器默认实施了严格的同源策略 (Same-Origin Policy),即只有当协议、域名和端口号都相同时,才认为两个 URL 属于同一个源。如果尝试跨越不同的源进行请求,则会触发跨域限制[^1]。 #### 2. **简单请求** 对于某些类型的请求(如 GET、POST 和 HEAD),只要它们不涉及自定义头部或者上传文件等复杂操作,就可以被视作“简单请求”。在这种情况下,浏览器会在后台自动添加必要的 CORS 相关头部,并等待来自目标服务器的支持响应。例如: - 如果服务端返回了合适的 `Access-Control-Allow-Origin` 字段值,则表示该次跨域调用成功; - 若缺少此字段或不符合预期设定,则会产生错误提示[^1]。 以下是简单的代码演示如何启用基本形式下的跨域支持: ```java @Configuration public class SimpleCorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**").allowedOrigins("*"); } }; } } ``` 注意,在实际生产环境中不应随意开放所有来源 (`"*"`) ,而应该限定具体的可信地址列表以提高安全性[^2]。 #### 3. **预检请求** 除了上述提到过的简易型之外,还有另外一种更为复杂的场景叫做 “预检请求”(Preflight Request) 。这类情况通常发生在以下条件下之一发生时: - 使用了非标准HTTP动词(GET/POST以外); - 自定义Header; - Content-Type 不属于下列三种 MIME 类型之一:`application/x-www-form-urlencoded`, `multipart/form-data`, 或者 plain text. 此时,浏览器会先发出一个带有 METHOD=OPTIONS 的额外请求询问服务器是否同意执行真正的动作之前的操作权限。这个过程被称为 preflight request (飞行前检查)。只有当服务器明确答复允许之后才会继续发送原始计划内的主要请求。 下面是一个关于 Preflight Requests 的 Java 配置实例展示怎样精确控制这些行为参数: ```java @Configuration public class AdvancedCorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://example.com", "https://anotherdomain.org") .allowedMethods("GET","POST","PUT","DELETE") .maxAge(3600L)//缓存preflight的结果时间为一个小时. .allowCredentials(true); } } ``` 这里设置了最大年龄(max-age),意味着在此期间内相同的preflights不需要再次查询;同时也开启了credentials选项以便处理那些需要认证信息随附的情况比如cookies等等[^2]. --- ### 总结 综上所述,CORS提供了一个灵活又强大的框架用来管理web应用间的交互关系,既保障了数据交换过程中应有的隐私保护措施又能促进合法合理的合作共享模式发展下去[^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值