filsh/yii2-oauth2server 是当前 Yii2 生态最成熟、开箱即用的封装,不建议从零集成 league/oauth2-server;它已深度适配 Yii2,处理了路由、过滤、模型绑定、迁移等耦合点。

OAuth2 服务器到底用哪个包?filsh/yii2-oauth2server 还是自己集成 league/oauth2-server?
直接说结论:filsh/yii2-oauth2server 是当前 Yii2 生态里最成熟、开箱即用的封装,不建议从零手搭 league/oauth2-server。它本质就是对 league/oauth2-server 的深度适配,已处理好路由、行为过滤、模型绑定、迁移脚本等 Yii2 特有耦合点。自己硬接 league/oauth2-server 要重写存储层(比如把 Pdo 换成 Yii2 的 Connection)、手动注册服务、补全 OpenID Connect 支持,最后发现踩的坑和 filsh 已解决的一模一样。
配置模块时 storageMap 和 grantTypes 最容易填错什么?
storageMap 不是“随便指定一个用户模型”,它要求该模型实现 \OAuth2\Storage\UserCredentialsInterface 接口——尤其 checkUserCredentials() 和 getUserDetails() 这两个方法必须返回符合 OAuth2 协议的数据结构(比如 getUserDetails() 必须返回 ['user_id' => $id],不能只返回 AR 对象)。grantTypes 里若启用 user_credentials,但没在 storageMap 中配 user_credentials,请求时会静默失败,日志里只报 "Invalid grant_type",实际是底层找不到对应存储器。
-
storageMap键名必须与 grant type 名称严格一致(如'user_credentials'→'user_credentials') -
user_credentials存储器类必须含密码校验逻辑,不能只查数据库;Yii2 原生的validatePassword()得手动调用 - 如果用
refresh_token,务必设'always_issue_new_refresh_token' => true,否则刷新后旧 token 仍有效,存在安全风险
为什么 /oauth2/token 接口返回 404 或 500,但 migrate 已执行?
常见原因不是代码问题,而是 URL 规则没生效或模块未挂载到正确入口。Yii2 的 oauth2 模块默认只响应 POST oauth2/token 这类 REST 路由,但如果你用的是高级模板或 API 模块结构,urlManager 的 rules 里没加这条:
"POST oauth2/<action>" => "oauth2/rest/<action>"
或者你把模块配在 frontend/config/main.php,却用 api/web/index.php 启动服务——模块根本没加载。另一个隐蔽问题是:数据库表名默认是 oauth_client 等单数形式,但有些项目用了复数表名(如 oauth_clients),这时得在 storageMap 里传自定义仓库类,而不是依赖默认 Pdo 存储器。
token 验证行为 CompositeAuth 怎么选 authMethods 才不冲突?
别一股脑全塞进去。HttpBearerAuth(Header 里 Authorization: Bearer xxx)和 QueryParamAuth(URL 里 ?access_token=xxx)可以共存,但 HttpBasicAuth 在 OAuth2 场景下基本不用——它走的是用户名密码校验,和 access_token 无关,混用会导致 findIdentityByAccessToken() 根本不被调用。真正要配的是:
- API 内部调用(如微服务间)→ 用
HttpBearerAuth - 前端 JS 调用(跨域限制无法发 Header)→ 加
QueryParamAuth,但必须限制仅用于调试环境,生产禁用 -
CompositeAuth的authMethods是“任一通过即放行”,不是“全部验证”,顺序不影响逻辑,但影响错误提示优先级
最后提醒一句:OAuth2 的核心不在“怎么生成 token”,而在于“谁有权限发 token”和“token 能换什么资源”。client_secret 存数据库明文、refresh_token 永不过期、access_token 有效期设成 30 天……这些配置项比写对一行 migration 更关键,也更容易被忽略。











