项目介绍
最近在做一个后台项目,目标是登录后无操作30分钟后自动过期,一直操作的情况下,过期时间一直刷新(目前不考虑每次操作修改对数据库的压力)
token有效期检测
操作后自动刷新过期时间
管理员手动登出其他登录用户
单用户登录,二次登录作废上次登录token
token有效期检测
passport自带就有检测过期时间,这个用过都了解\
文件在League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator
public function validateAuthorization(ServerRequestInterface $request)
{
.
.
.
try {
// Attempt to parse and validate the JWT
// 这里会根据token解析出过期时间
/**
* 内容为这个
* "exp" => Lcobucci\JWT\Claim\GreaterOrEqualsTo^ {#2944
* -name: "exp"
* -value: 1606462560
* }
**/
$token = (new Parser())->parse($jwt);
.
.
.
// Ensure access token hasn't expired
$data = new ValidationData();
$data->setCurrentTime(time());
// 这里验证token是否有效
if ($token->validate($data) === false) {
throw OAuthServerException::accessDenied('Access token is invalid');
}
// Check if token has been revoked
// 这样验证数据库中token是否已经被撤销,会进行一次查询
// 最后验证结束还是查询一次,把查询内容放到auth('api')->user()->token()中
if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) {
throw OAuthServerException::accessDenied('Access token has been revoked');
}
.
.
.
}
操作后自动刷新过期时间
这个是目前遇到的问题,在数据库中可以看到oauth_access_tokens中,有 expires_at 字段,理所当然的,请求之后,修改这个过期时间
// $this->loginUser为自定义的,相当于$request->user('api')
$this->loginUser->token()->expires_at = Carbon::now()->addMinutes(30);
$this->loginUser->token()->save();
实际上用该token请求还是没有问题,百思不得其解后,找到问题所在
// Ensure access token hasn't expired
$data = new ValidationData();
$data->setCurrentTime(time());
// 这里验证token是否有效
if ($token->validate($data) === false) {
throw OAuthServerException::accessDenied('Access token is invalid');
}
这里只验证了token中存储的过期时间
if ($this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti'))) {
throw OAuthServerException::accessDenied('Access token has been revoked');
}
这里只验证了是否撤销(数据库 revoked 字段)
也就是说根本没有验证数据库的过期字段,再怎么修改过期时间也是无效的(因为只做存储查看作用,没实际验证)\
passport目前想要自己刷新过期时间,又不改变token的情况下,只能进行自定义一个中间件来解决了\
通过 $this->loginUser->token()->expires_at 来获取过期时间,然后自定义处理逻辑
管理员手动登出其他登录用户
这个就比较简单了
DB::table('oauth_access_tokens')->where('user_id', $user->id)
->update([
'revoked' => 1
]);
直接作废该用户的所有 token 就完成了
单用户登录,二次登录作废上次登录token
这个和上面同理,通过 $this->loginUser->token()->getQueueableId() 获取当前登录用户数据库中对应的id
DB::table('oauth_access_tokens')->where('user_id', $this->loginUser->id)
->where('id', '!=', $this->loginUser->token()->getQueueableId())
->update([
'revoked' => 1
]);
直接作废该用户的其他 token 就完成了
目前只能想到通过自定义中间件来处理刷新token有效时间来解决,如果有什么比较好的办法,欢迎讲解!