CORS 解释
(跨域资源共享)的检查是由浏览器端实现的。浏览器通过一系列的安全策略来保护用户免受恶意网站的攻击,其中同源策略(Same-Origin Policy)是核心之一。CORS 是对同源策略的一种补充机制,允许浏览器在满足特定条件下跨域请求资源。
CORS 的工作原理
CORS 的检查主要涉及以下几个步骤,这些步骤都由浏览器自动完成:
预检请求(Preflight Request):
当浏览器检测到跨域请求时,会先发送一个 OPTIONS 请求到目标服务器,这个请求称为“预检请求”。
预检请求的目的是询问服务器是否允许当前的跨域请求。浏览器会在 OPTIONS 请求的头部中添加以下字段:
Origin:表示请求发起的源(协议、域名和端口)。
Access-Control-Request-Method:表示实际请求将使用的 HTTP 方法(如 GET、POST、PUT 等)。
Access-Control-Request-Headers:表示实际请求中自定义的请求头。服务器响应:
服务器需要在响应中明确告诉浏览器是否允许该跨域请求。服务器会在响应头中返回以下字段:
Access-Control-Allow-Origin:指定允许访问的来源。可以是具体的 URL(如 http://example.com),也可以是 *(允许所有来源)。
Access-Control-Allow-Methods:允许的 HTTP 方法。
Access-Control-Allow-Headers:允许的自定义请求头。
Access-Control-Allow-Credentials:是否允许携带用户凭证(如 Cookie)。
Access-Control-Max-Age:预检请求结果的缓存时间(单位为秒)。浏览器检查:
浏览器收到服务器的响应后,会检查响应头中的 CORS 字段是否满足请求的要求。
如果满足要求,浏览器会继续发送实际的请求(如 GET、POST 等)。
如果不满足要求,浏览器会阻止实际请求的发送,并在控制台中报错(如 No ‘Access-Control-Allow-Origin’ header is present on the requested resource)。
Cors 设置了,为什么无效?
如果使用的是restController,添加Cors需要在其他行为之前,否则可能导致提前就报错。如下:
public function behaviors()
{
$behaviors = parent::behaviors();
//cors 放在最前面
return array_merge([
'corsFilter' => [
'class' => \yii\filters\Cors::class,
]
], $behaviors);
}
同时需要注意的是,如果cors设置在控制器behavior,系统发生异常等会跳过behavior的执行,放在全局配置比较妥:
'as cors' => [
'class' => \yii\filters\Cors::className(),
]