跨域资源共享 (CORS) 是一种基于 HTTP 头的安全机制,允许服务器指示浏览器应允许从其自身以外的任何来源(域名、协议或端口)加载资源。

CORS 通过在 HTTP 请求和响应中添加头来工作,以指示请求的资源是否可以跨不同来源共享,从而帮助防止恶意攻击,如跨站请求伪造 (CSRF) 和数据盗窃。

如果你不熟悉 CORS 和 CORS 头,请阅读 MDN 上的 CORS 文档

CodeIgniter 提供了 CORS 过滤器和 helper 类。

  • 配置 CORS

  • 设置默认配置

  • 启用 CORS

  • 检查路由和过滤器

  • 设置其他配置

  • 配置 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

    处理预检请求。