Yii3.0实现无状态JWT认证需禁用session、替换User组件、重写getIdentity()方法,并通过CompositeAuth或手动逻辑校验token;使用lcobucci/jwt生成含exp/iat/uid的签名token,密钥须从环境变量读取。

在Yii3.0中实现真正的无状态JWT认证,必须绕过默认的session依赖机制,否则每次请求仍会尝试读写session,导致token校验被跳过、登录态无法持久、跨请求鉴权失败。
替换默认User组件并禁用session
第一步:在api/config/web.php中将user组件替换为自定义类,并关闭session自动启动:
【enableSession => false】必须设置,否则JWT无状态特性会被覆盖;若同时存在Web模块和API模块,此配置仅作用于API模块,Web模块可保留session。
第二步:创建app\components\JwtUser类,继承yii\web\User,重写getIdentity()方法——该方法不再从session取用户,而是从Authorization: Bearer <token>头中提取并解码验证。
第三步:在配置中指定新User类:'class' => 'app\components\JwtUser',同时确保identityClass指向实现了IdentityInterface的模型(如app\models\User)。
配置REST控制器的认证行为
方法一:使用CompositeAuth组合多种认证方式
在API控制器的behaviors()中添加:
'authenticator' => [ 'class' => yii\filters\auth\CompositeAuth::class, 'authMethods' => [ yii\filters\auth\HttpBearerAuth::class, ], ]
这会自动拦截请求,提取Authorization头中的Bearer token并交由HttpBearerAuth处理。
方法二:手动注入JWT验证逻辑(更可控)
不依赖HttpBearerAuth,直接在beforeAction()中调用自定义JWT解析器,捕获ExpiredException或SignatureInvalidException并返回401响应。
注意:若使用方法二,必须确保Yii::$app->user->setIdentity($identity)被显式调用,否则后续Yii::$app->user->id将为空。
生成与验证JWT token的核心逻辑
第一步:安装lcobucci/jwt库(Yii3.0推荐,替代已废弃的firebase/php-jwt)
composer require lcobucci/jwt:^4.0
第二步:在app\components\JwtAuth中实现generateToken($userId)
使用Lcobucci\JWT\Signer\Hmac\Sha256签名,payload中必须包含exp(秒级时间戳)、iat、uid字段;【密钥必须与验证时完全一致,且不可硬编码在代码中】,应从环境变量读取。
第三步:在getIdentity()中解析token
先用Lcobucci\JWT\Parser拆解token三段,再用Configuration::forSymmetricSigner()构建验证器,调用$token->validate($constraints)检查过期与签名;验证失败时抛出异常,由全局error handler转为JSON格式401响应。
第四步:从payload提取uid,调用User::findIdentity($uid)获取用户实例,返回该实例即完成认证链路。


















