You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel登录时如何保存PassportToken?API存Token到Cookie遇Key重复生成问题

在Laravel登录时将Passport Token存储到Cookie的解决方案

嘿,我来帮你搞定这个问题!你遇到的每次生成不同Key的情况,大概率是因为之前在Home控制器里每次请求都重新生成了Token,或者没正确复用Passport的Token实例。下面是一步步的靠谱实现方案:


1. 重写登录成功后的逻辑,生成Token并存入Cookie

我们可以在默认的LoginController里重写authenticated方法,这样登录成功后就能直接处理Token和Cookie的逻辑:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use Laravel\Passport\TokenRepository;
use Laravel\Passport\RefreshTokenRepository;

class LoginController extends Controller
{
    // ... 其他默认代码

    protected function authenticated(Request $request, $user)
    {
        // 先吊销用户已有的所有Token,避免重复生成导致的多Token问题
        $tokenRepo = app(TokenRepository::class);
        $refreshTokenRepo = app(RefreshTokenRepository::class);
        
        $tokenRepo->revokeAccessTokenByUserId($user->id);
        $refreshTokenRepo->revokeRefreshTokensByUserId($user->id);

        // 生成新的Passport访问Token
        $accessToken = $user->createToken('LoginSessionToken')->accessToken;

        // 将Token存入Cookie,这里设置了1天有效期,同时开启HttpOnly防XSS
        return redirect()->intended('/home')->cookie(
            'passport_token',
            $accessToken,
            1440, // 有效期(分钟):1440=1天
            null,
            null,
            false, // 是否仅HTTPS环境发送?根据你的部署情况调整
            true   // 开启HttpOnly,禁止前端JS读取,提升安全性
        );
    }
}

2. 解决“每次生成不同Key”的核心问题

之前你在Home控制器里生成Token,会导致每次请求都创建新的Token实例,自然Key不一样。而上面的方法是仅在登录成功时生成一次Token,并持久化到Cookie中,后续请求直接复用这个Token即可。

另外要检查你的.env文件里的APP_KEY是否固定——这个是Laravel加密系统的核心,如果APP_KEY频繁变化,会导致加密/解密后的内容不一致,务必确保这个值稳定。

3. 让后续请求自动带上Cookie里的Token

为了让API能识别Cookie中的Token,我们可以写一个中间件,把Cookie里的Token转成Authorization: Bearer请求头:

// 创建中间件:php artisan make:middleware CookieToBearerToken

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CookieToBearerToken
{
    public function handle(Request $request, Closure $next)
    {
        // 如果Cookie里存在passport_token,就设置到请求头
        if ($request->hasCookie('passport_token')) {
            $token = $request->cookie('passport_token');
            $request->headers->set('Authorization', "Bearer {$token}");
        }

        return $next($request);
    }
}

然后在app/Http/Kernel.php里把这个中间件加到api或者web路由组里:

protected $middlewareGroups = [
    'web' => [
        // ... 其他中间件
        \App\Http\Middleware\CookieToBearerToken::class,
    ],

    'api' => [
        // ... 其他中间件
        \App\Http\Middleware\CookieToBearerToken::class,
    ],
];

4. 注销登录时清理Cookie和Token

别忘了在注销时同时吊销Token并清除Cookie,避免无效Token残留:

use Illuminate\Http\Request;
use Laravel\Passport\TokenRepository;
use Laravel\Passport\RefreshTokenRepository;

class LogoutController extends Controller
{
    protected function loggedOut(Request $request)
    {
        $user = auth()->user();
        if ($user) {
            $tokenRepo = app(TokenRepository::class);
            $refreshTokenRepo = app(RefreshTokenRepository::class);
            
            $tokenRepo->revokeAccessTokenByUserId($user->id);
            $refreshTokenRepo->revokeRefreshTokensByUserId($user->id);
        }

        // 清除Cookie
        return redirect('/')->cookie(
            'passport_token',
            null,
            -1 // 设置为负数值,让Cookie立即过期
        );
    }
}

额外注意事项

  • 确保你已经正确安装并配置了Laravel Passport:运行过php artisan passport:install,并且在User模型里添加了HasApiTokens trait;
  • 可以根据业务需求调整Token的有效期,在AuthServiceProvider的boot方法里设置:
    use Laravel\Passport\Passport;
    
    public function boot()
    {
        $this->registerPolicies();
        Passport::routes();
        
        Passport::tokensExpireIn(now()->addDays(1)); // 设置Token有效期1天
        Passport::refreshTokensExpireIn(now()->addDays(7)); // 刷新Token有效期7天
    }
    

内容的提问来源于stack exchange,提问作者Ahmed Shams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 06:57:42