Sanctum 授权验证这样调整是否合理
<?php
namespace App\Providers;
use App\Models\Sanctum\PersonalAccessToken;
use Carbon\Carbon;
use Illuminate\Foundation\Auth\User;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Sanctum\Sanctum;
class AuthServiceProvider extends ServiceProvider
{
/**
* The model to policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
//
];
/**
* Register any authentication / authorization services.
*/
public function boot(): void
{
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
Sanctum::authenticateAccessTokensUsing(function (PersonalAccessToken $accessToken, bool $isValid) {
// 如果本來是有效或者還在有效期內
if ($isValid || !$accessToken->expires_at->isPast()) {
return $isValid;
}
// 最後使用時間
$lastUsedAt = Carbon::createFromTimestamp(redis()->zscore('access_tokens_last_used_at', $accessToken->id));
// 有效期
$expiration = request()->is(config('c.backend_prefix') . '/*')
? config('c.backend_login_expiration')
: config('c.frontend_login_expiration');
// 如果使用時間+有效時間是大於當前時間
if ($lastUsedAt->addMinutes($expiration)->isPast()) {
return false;
}
// 防止並發請求(防止多次去無效更新)
if (cache()->lock("access_token_update_expires_at:$accessToken->id", 10)->get()) {
// 更新到期時間
$accessToken->update(['expires_at' => now()->addMinutes($expiration)]);
}
return true;
});
}
}
<?php
namespace App\Models\Sanctum;
use Illuminate\Support\Carbon;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;
/**
* @property int $id
* @property string $tokenable_type
* @property int $tokenable_id
* @property string $name
* @property string $token
* @property string $abilities
* @property Carbon $last_used_at
* @property Carbon $expires_at
* @property Carbon $created_at
* @property Carbon $updated_at
*/
class PersonalAccessToken extends SanctumPersonalAccessToken
{
protected static function booted(): void
{
static::saving(function (self $model) {
// 如果存在最後更新時間
if (in_array('last_used_at', array_keys($model->getDirty()))) {
// 更新到redis 不更新到數據庫
redis()->zadd('access_tokens_last_used_at', time(), $model->id);
return false;
}
return true;
});
static::saved(function (self $model) {
cache()->forget("access_token:$model->token");
});
}
/**
* 查找token
*
* @param $token
* @return static|null
*/
public static function findToken($token): ?static
{
$index = ($index = strpos($token, '|')) === false ? 0 : $index + 1;
$key = 'access_token:' . hash('sha256', substr($token, $index));
return cache()->remember($key, 3600, function () use ($token) {
return parent::findToken($token);
});
}
}
有用这个包的大佬们可以交流一下
个人认为缓存相关的内容不应该放到 model 类里,应该重写 sanctum 的 Guard 类