当前位置: 首页 > news >正文

对Yii2中开启`authenticator`后出现的跨域问题-修复

针对Yii2中开启authenticator后出现的跨域问题,以下是优化后的解决方案。主要修复点包括正确处理OPTIONS预检请求修复认证器配置优化CORS设置

<?php
namespace app\controllers;use app\models\SystemLog;
use Yii;
use yii\filters\Cors;
use yii\rest\Controller;
use yii\filters\auth\HttpBearerAuth;
use yii\web\UnauthorizedHttpException;class ApiController extends Controller
{// 日志级别常量const LOG_LEVEL_INFO = 'info';const LOG_LEVEL_WARNING = 'warning';const LOG_LEVEL_ERROR = 'error';public function behaviors(){$behaviors = parent::behaviors();// 移除默认的认证器unset($behaviors['authenticator']);// CORS 优先 - 修复关键点:允许Authorization头$behaviors['corsFilter'] = ['class' => Cors::class,'cors' => ['Origin' => Yii::$app->params['allowedOrigins'] ?? ['http://localhost:3002', 'http://api.mfe.local'],'Access-Control-Allow-Credentials' => true,'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],'Access-Control-Request-Headers' => ['*'], // 允许所有头'Access-Control-Expose-Headers' => ['*'],  // 暴露所有头给客户端'Access-Control-Max-Age' => 86400,],];// 认证器配置 - 修复关键点:正确排除OPTIONS$behaviors['authenticator'] = ['class' => HttpBearerAuth::class,'except' => array_merge(['options'], $this->authOptional()),];// 日志过滤器(最后执行)$behaviors['requestLogger'] = new class extends \yii\base\ActionFilter {public function beforeAction($action){if (!Yii::$app->request->isOptions) {Yii::info(['action' => $action->id,'request' => Yii::$app->request->rawBody,'headers' => Yii::$app->request->headers->toArray(),], 'api_requests');}return parent::beforeAction($action);}];return $behaviors;}// 确保OPTIONS方法被排除 - 修复关键点protected function authOptional(){return ['options'];}// 处理OPTIONS请求 - 新增方法public function actionOptions(){Yii::$app->response->statusCode = 200;return [];}// 认证失败处理 - 跳过OPTIONS请求public function beforeAction($action){if (!parent::beforeAction($action)) {return false;}// 关键修复:跳过OPTIONS请求的认证检查if (Yii::$app->request->isOptions) {return true;}if (Yii::$app->user->isGuest && !in_array($action->id, $this->authOptional())) {throw new UnauthorizedHttpException('登录已过期,请重新登录');}return true;}/* 其余方法保持不变(getId, getWid, afterAction, success, error等) */// ...
}

关键修复说明:

  1. CORS配置优化

    'Access-Control-Request-Headers' => ['*'],     // 允许所有请求头
    'Access-Control-Expose-Headers' => ['*'],      // 暴露所有响应头
    

    确保浏览器能传递和处理Authorization

  2. 认证器配置修复

    unset($behaviors['authenticator']); // 移除默认认证器
    $behaviors['authenticator'] = ['except' => array_merge(['options'], $this->authOptional()),
    ];
    

    显式排除OPTIONS请求,避免预检请求被拦截

  3. OPTIONS请求处理

    public function actionOptions()
    {Yii::$app->response->statusCode = 200;return [];
    }
    

    添加专门的OPTIONS处理器返回空响应

  4. 认证检查跳过OPTIONS

    public function beforeAction($action)
    {// ...if (Yii::$app->request->isOptions) {return true; // 直接放行OPTIONS请求}// ...
    }
    
  5. 跨域白名单扩展(可选):
    在配置文件中增加更多允许的源:

    // config/params.php
    return ['allowedOrigins' => ['http://localhost:3002','http://api.mfe.local','https://your-production-domain.com'],
    ];
    

补充建议:

  1. Nginx/Apache配置
    确保服务器配置允许跨域头:

    # Nginx配置示例
    add_header 'Access-Control-Allow-Origin' $http_origin always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' '*' always;
    
  2. 前端Axios配置
    确保请求携带凭证:

    // 前端请求配置
    axios.defaults.withCredentials = true;
    
  3. 测试预检请求
    使用curl测试OPTIONS请求:

    curl -X OPTIONS http://api.mfe.local/api/user/info \-H "Origin: http://localhost:3002" \-H "Access-Control-Request-Method: GET" \-H "Access-Control-Request-Headers: authorization" \-I
    

这些修改确保:

  1. OPTIONS预检请求正确处理
  2. Authorization头能被跨域传递
  3. 认证中间件不会拦截预检请求
  4. 服务器返回正确的CORS响应头

修复后,带Bearer Token的跨域请求流程:

浏览器API服务器OPTIONS预检请求跳过认证检查返回CORS头(200)实际请求(GET/POST...)检查Bearer Token返回数据(200)返回401错误alt[认证成功][认证失败]浏览器API服务器

实测成功
【关键在于】
在这里插入图片描述

在这里插入图片描述

http://www.lryc.cn/news/592505.html

相关文章:

  • 高通8255 Android Virtio Virtio-SPI 配置方法
  • 当OT遇见IT:Apache IoTDB如何用“时序空间一体化“技术破解工业物联网数据孤岛困局?
  • RSTP技术
  • 图书系统(新)
  • 文件上传 ,显示文件列
  • [3-02-01].第01章:框架概述 - Spring生态
  • QT窗口(4)-浮动窗口
  • 如何阅读Spring源码
  • JavaSE -- 数据操作流
  • 亚马逊广告高级玩法:如何通过ASIN广告打击竞品流量?
  • 利用steps()分步实现奔跑的小熊案例
  • IDEA 中 Maven 配置:当前项目与新项目的统一设置方法
  • 基于单片机金沙河粮仓环境监测系统设计与实现
  • STM32之L298N电机驱动模块
  • Maven 配置文件核心配置:本地仓库、镜像与 JDK 版本
  • JVM常用运行时参数说明
  • sizeof和strlen的区别
  • 【AI News | 20250717】每日AI进展
  • 通信算法之294:LTE系统中的整数倍频偏估计
  • 【数据结构初阶】--双向链表(一)
  • 【Python】python 爬取某站视频批量下载
  • stack and queue 之牛刀小试
  • SymAgent(神经符号自学习Agent)
  • 实习十三——传输层协议
  • 多级反馈队列
  • JS获取 CSS 中定义var变量值
  • 路由的概述
  • 饿了么app 抓包 hook
  • three初体验
  • 【基座模型】Qwen3报告总结