跨域资源共享 (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
检查请求是否为预检请求。