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);
        });
    }
}
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 5

有用这个包的大佬们可以交流一下

6个月前 评论

个人认为缓存相关的内容不应该放到 model 类里,应该重写 sanctum 的 Guard 类

6个月前 评论
cccdz (楼主) 6个月前
cccdz (楼主) 6个月前
cccdz (楼主) 6个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!