Laravel登录时如何保存PassportToken?API存Token到Cookie遇Key重复生成问题
嘿,我来帮你搞定这个问题!你遇到的每次生成不同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模型里添加了HasApiTokenstrait; - 可以根据业务需求调整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
相关产品推荐
相关产品推荐

