跨域资源共享 (CORS)
在 4.5.0 版本加入.
跨域资源共享 (CORS) 是一种基于 HTTP 头的安全机制,允许服务器指示浏览器应允许从其自身以外的任何来源(域名、协议或端口)加载资源。
CORS 通过在 HTTP 请求和响应中添加头来工作,以指示请求的资源是否可以跨不同来源共享,从而帮助防止恶意攻击,如跨站请求伪造 (CSRF) 和数据盗窃。
如果你不熟悉 CORS 和 CORS 头,请阅读 MDN 上的 CORS 文档。
CodeIgniter 提供了 CORS 过滤器和 helper 类。
配置 CORS
设置默认配置
可以通过 app/Config/Cors.php 配置 CORS。
至少需要设置 $default
属性中的以下项目:
allowedOrigins
: 明确列出你想要允许的来源。allowedHeaders
: 明确列出你想要允许的 HTTP 头。allowedMethods
: 明确列出你想要允许的 HTTP 方法。
警告
基于最小特权原则,只应允许必要的最小来源、方法和头。
如果你在跨域请求中发送凭证(例如,cookies),请将 supportsCredentials
设置为 true
。
启用 CORS
要启用 CORS,你需要做两件事:
为允许 CORS 的路由指定
cors
过滤器。为 CORS 预检请求添加 OPTIONS 路由。
设置路由
你可以在 app/Config/Routes.php 中为路由设置 cors
过滤器。
例如,
<?php
use CodeIgniter\Router\RouteCollection;
$routes->group('', ['filter' => 'cors'], static function (RouteCollection $routes): void {
$routes->resource('product');
$routes->options('product', static function () {
// Implement processing for normal non-preflight OPTIONS requests,
// if necessary.
$response = response();
$response->setStatusCode(204);
$response->setHeader('Allow:', 'OPTIONS, GET, POST, PUT, PATCH, DELETE');
return $response;
});
$routes->options('product/(:any)', static function () {});
});
不要忘记为预检请求添加 OPTIONS 路由。因为如果路由不存在,控制器过滤器(必需过滤器除外)将不起作用。
CORS 过滤器处理所有预检请求,因此通常不会调用 OPTIONS 路由的闭包控制器。
在 Config\Filters 中设置
或者,你可以在 app/Config/Filters.php 中为 URI 路径设置 cors
过滤器。
例如,
<?php
namespace Config;
use CodeIgniter\Config\Filters as BaseFilters;
// ...
class Filters extends BaseFilters
{
// ...
public array $filters = [
// ...
'cors' => [
'before' => ['api/*'],
'after' => ['api/*'],
],
];
}
不要忘记为预检请求添加 OPTIONS 路由。因为如果路由不存在,控制器过滤器(必需过滤器除外)将不起作用。
例如,
<?php
use CodeIgniter\Router\RouteCollection;
$routes->group('', ['filter' => 'cors'], static function (RouteCollection $routes): void {
$routes->options('api/(:any)', static function () {});
});
CORS 过滤器处理所有预检请求,因此通常不会调用 OPTIONS 路由的闭包控制器。
检查路由和过滤器
配置完成后,你可以使用 spark 路由 命令检查路由和过滤器。
设置其他配置
如果你想使用不同于默认配置的配置,请在 app/Config/Cors.php 中添加一个属性。
例如,添加 $api
属性。
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
/**
* Cross-Origin Resource Sharing (CORS) Configuration
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
*/
class Cors extends BaseConfig
{
// ...
public array $api = [
'allowedOrigins' => ['https://app.example.com'],
'allowedOriginsPatterns' => [],
'supportsCredentials' => true,
'allowedHeaders' => ['Authorization', 'Content-Type'],
'exposedHeaders' => [],
'allowedMethods' => ['GET', 'POST', 'PUT', 'DELETE'],
'maxAge' => 7200,
];
}
属性名称(在上述示例中为 api
)将成为配置名称。
然后,像 cors:api
一样将属性名称指定为过滤器参数:
<?php
use CodeIgniter\Router\RouteCollection;
$routes->group('api', ['filter' => 'cors:api'], static function (RouteCollection $routes): void {
$routes->resource('user');
$routes->options('user', static function () {});
$routes->options('user/(:any)', static function () {});
});
你也可以使用 过滤器参数。
类参考
- class CodeIgniter\HTTP\Cors
- CodeIgniter\HTTP\Cors::addResponseHeaders(RequestInterface $request, ResponseInterface $response) ResponseInterface
- 参数:
$request (
RequestInterface
) – 请求实例$response (
ResponseInterface
) – 响应实例
- 返回:
响应实例
- 返回类型:
ResponseInterface
添加 CORS 的响应头。
- CodeIgniter\HTTP\Cors::handlePreflightRequest(RequestInterface $request, ResponseInterface $response) ResponseInterface
- 参数:
$request (
RequestInterface
) – 请求实例$response (
ResponseInterface
) – 响应实例
- 返回:
响应实例
- 返回类型:
ResponseInterface
处理预检请求。
- CodeIgniter\HTTP\Cors::isPreflightRequest(IncomingRequest $request) bool
- 参数:
$request (
IncomingRequest
) – 请求实例
- 返回:
如果是预检请求则返回 True。
- 返回类型:
bool
检查请求是否为预检请求。