为什么Lumen中oauth_access_tokens的expires_at字段未生效?
问题1:access_token过期后仍可访问的解决方案
根因说明
你使用的dusterio/lumen-passport:0.3.4版本适配Lumen时,默认只校验access_token是否存在、是否被撤销,没有内置expires_at字段的校验逻辑,所以只会查询token的id匹配结果,不会判断过期时间。
修复步骤
- 第一步:创建自定义校验中间件,新增过期时间判断
在app/Http/Middleware目录下新建PassportCustomAuth.php:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Auth\AuthenticationException; use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory; class PassportCustomAuth { protected $server; protected $tokens; public function __construct(ResourceServer $server, TokenRepository $tokens) { $this->server = $server; $this->tokens = $tokens; } public function handle($request, Closure $next) { $psr = (new DiactorosFactory)->createRequest($request); try { $psr = $this->server->validateAuthenticatedRequest($psr); } catch (OAuthServerException $e) { throw new AuthenticationException; } $tokenId = $psr->getAttribute('oauth_access_token_id'); $token = $this->tokens->find($tokenId); // 新增过期时间、撤销状态校验 if (!$token || $token->expires_at->lt(now()) || $token->revoked) { throw new AuthenticationException('令牌已过期或失效'); } $request->attributes->add([ 'oauth_access_token_id' => $tokenId, 'oauth_client_id' => $psr->getAttribute('oauth_client_id'), 'oauth_user_id' => $psr->getAttribute('oauth_user_id'), 'oauth_scopes' => $psr->getAttribute('oauth_scopes'), ]); return $next($request); } }
- 第二步:替换默认的auth中间件
在bootstrap/app.php中修改路由中间件注册配置:
$app->routeMiddleware([ 'auth' => App\Http\Middleware\PassportCustomAuth::class, // 其他原有中间件保留即可 ]);
- 第三步:确认Token模型的时间格式配置
如果校验时出现时间类型错误,可以自定义Token模型,添加日期自动转换配置:
<?php namespace App\Models; use Laravel\Passport\Token as BaseToken; class Token extends BaseToken { protected $dates = [ 'expires_at', ]; }
问题2:oauth_refresh_tokens表的作用与使用方法
核心作用
- 存储access_token对应的刷新令牌,用于access_token过期后免密换发新的令牌,不需要用户重新输入账号密码登录,提升使用体验。
- 刷新令牌自身也有有效期,默认比access_token长很多,你可以通过
LumenPassport::refreshTokensExpireIn()方法自定义刷新令牌的有效期,到期后用户才需要重新走账号密码登录流程。
使用方法
当access_token过期后,调用/api/oauth/token接口,按如下参数请求即可换发新令牌:
{ "grant_type": "refresh_token", "refresh_token": "登录接口返回的refresh_token值", "client_id": "你的客户端ID", "client_secret": "你的客户端密钥" }
请求成功后会返回新的access_token和refresh_token,旧的access_token和refresh_token会被自动标记为失效。
内容的提问来源于stack exchange,提问作者mstdmstd
相关产品推荐
相关产品推荐

