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

对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.xdnf.cn/news/15771.html

相关文章:

  • 图机器学习(11)——链接预测
  • 现代R语言【Tidyverse、Tidymodel】的机器学习方法
  • Typecho博客集成阿里云CDN+OSS实现全站加速方案
  • 关于字符编辑器vi、vim版本的安装过程及其常用命令:
  • 第七章 愿景09 海波龙的坑
  • 数字化转型:概念性名词浅谈(第三十讲)
  • Kotlin集合过滤
  • 文档处理控件TX Text Control系列教程:使用 C# .NET 将二维码添加到 PDF 文档
  • 从拆分到导出图片,这款工具如何简化PDF处理流程
  • 基于R语言piecewiseSEM结构方程模型在生态环境领域实践技术应用
  • 无标记点动捕:如何突破传统娱乐边界,打造沉浸式交互体验
  • RuoYi-Cloud框架功能分析与请求处理流程解析
  • docker,防火墙关闭后,未重启docker,导致端口映射失败
  • 【3D并排条状图】:附Origin详细画图教程
  • CertiK创始人顾荣辉出席上海Conflux大会,聚焦Web3全球化中的安全与合规路径
  • 区块链加密技术全景解析
  • (nice!!!)(LeetCode 每日一题) 2163. 删除元素后和的最小差值 (贪心+优先队列)
  • Java学习第五十三部分——后端常用函数
  • 从抓包GitHub Copilot认证请求,认识OAuth 2.0技术
  • 性能远超Spring Cloud Gateway!Apache ShenYu如何重新定义API网关!
  • 集成开发环境:在IntelliJ IDEA中高效运行与调试Spring Boot
  • LangChain 源码剖析(三):连接提示词与大语言模型的核心纽带——LLMChain
  • Mock 单元测试
  • AI驱动数据质量优化:破局数据治理难题
  • PyCharm高效入门指南
  • 力扣 hot100 Day48
  • 雪豹大模型驱动效率革命 华鼎冷链科技重构餐饮供应链神经网络
  • 寻找数组中的多数元素:HashMap方法解析
  • 元宇宙与Web3的深度融合:构建沉浸式数字体验的愿景与挑战
  • Elasticsearch+Logstash+Filebeat+Kibana部署【7.1.1版本】