yii2集成jwt需手动衔接三处:启用rest路由模式、在控制器行为中挂载自定义bearer认证类、将解析出的用户身份写回\yii::$app->user;否则identity为null、401静默或响应错乱。

Yii2 的 RESTful 接口集成 JWT 不是“装个扩展就自动生效”,关键在于三处手动衔接:路由规则启用 REST 模式、控制器行为中正确挂载 Bearer 认证、以及 token 解析后必须把用户身份写回 \Yii::$app->user,否则 $this->user->identity 始终为 null。
为什么 HttpBearerAuth 直接用会静默失败
Yii2 自带的 yii\filters\auth\HttpBearerAuth 只校验 Authorization: Basic xxx 头,对 Bearer eyJ0eXAi... 完全不识别——它根本没解析 JWT 结构,也不验证签名或过期时间。直接塞进 behaviors() 会导致所有带 Authorization 头的请求都返回 401,且无日志提示具体原因。
必须自定义认证类,例如 JwtHttpBearerAuth,在 authenticate() 中做三件事:
- 从
$request->getHeaders()->get('Authorization')提取 token 字符串,并用preg_match('/^Bearer\s+(.*?)$/', $auth, $matches)严格匹配空格分隔(少一个空格就失败) - 调用
lcobucci/jwt的(new Parser())->parse($matches[1])解析,捕获Lcobucci\JWT\Exception并转为UnauthorizedHttpException - 从 payload 中取出
user_id,再调用User::findIdentity($userId)实例化 Identity,最后返回该对象(这才是$this->user->identity有值的前提)
urlManager 配置 REST 规则时容易漏掉的关键项
光写 ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/user'] 不够,enablePrettyUrl 和 enableStrictParsing 必须同时开启,否则 GET /v1/users 会被当成普通路由忽略,直接 404;更隐蔽的问题是:如果没设 'pluralize' => true(默认为 true),UserController 对应的路径是 /v1/user 而非 /v1/users,前端调用时会反复踩 404。
推荐最小可用配置:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'v1/user',
'pluralize' => true,
],
],
],
token 过期或签名错误时,为什么 error handler 捕不到异常
因为 JWT 校验失败抛出的是 Lcobucci\JWT\Exception 或 sizeg\jwt\exceptions\JwtException,而 Yii2 默认的 errorHandler 只捕获继承自 Exception 和 Error 的异常,但不会主动处理这些第三方扩展异常。结果就是:token 错误时接口直接返回空白响应或 500,而不是预期的 401 + JSON 错误体。
解决方法是在全局 catchAll 或模块 beforeAction 中手动捕获:
- 在
config/web.php的components.errorHandler中加'errorAction' => 'v1/error' - 在
controllers/v1/ErrorController.php的actionIndex()里,检查\Yii::$app->errorHandler->exception是否为 JWT 相关异常,如果是,显式设置\Yii::$app->response->setStatusCode(401)并返回['code' => 401, 'message' => 'Invalid or expired token']
API 控制器里调 $this->render() 会导致 JSON 响应混入 HTML
这是最常被忽略的硬伤。yii\rest\ActiveController 默认动作(如 actionIndex())返回数组即可自动转 JSON;但一旦你在代码里写了 $this->render('index', [...]),Yii 就会走视图渲染流程,最终输出的是 HTML 文本,和 Content-Type: application/json 冲突,前端解析直接报错。
务必确认以下三点:
- 控制器继承的是
yii\rest\Controller或yii\rest\ActiveController,不是yii\web\Controller - 所有返回语句都是
return ['data' => $model]或return $model->attributes这类纯数据结构 - 在
config/web.php的response组件中已设'format' => \yii\web\Response::FORMAT_JSON,且未被子模块覆盖
JWT 在 Yii2 里从来不是开箱即用的“功能开关”,而是需要你亲手把 token 解析、用户加载、异常映射这三根线拧紧。任何一环松动,都会导致 401 静默、identity 为空、或响应格式错乱——这些都不是配置遗漏,而是逻辑断点。











