我正在开发一个 Laravel 10 应用程序,该应用程序带有中间件来检查令牌是否已过期。如果有,它会使用
refresh_token
生成新令牌,创建新会话,并使用新数据(令牌、刷新和 expires_at)更新会话。
中间件
namespace App\Http\Middleware;
use Closure;
use Carbon\Carbon;
use Nanicas\Auth\Services\ThirdPartyAuthService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
class NanicasAuthenticateMiddleware
{
public function handle(Request $request, Closure $next)
{
$auth = $request->session()->get('nanicas');
if (empty($auth)) {
return $this->logout($request);
}
if (!Carbon::now()->greaterThanOrEqualTo($auth['expires_at_datetime'])) {
return $next($request);
}
$config = config('nanicas');
$authService = app()->make(ThirdPartyAuthService::class);
$authResponse = $authService->refreshToken([
'grant_type' => 'refresh_token',
'client_id' => $config['CLIENT_ID'],
'client_secret' => $config['CLIENT_SECRET'],
'refresh_token' => $auth['refresh_token'],
'scope' => '',
]);
if (!$authResponse['status']) {
return $this->logout($request);
}
$request->session()->regenerate();
$request->session()->put('nanicas', $authResponse['body']);
return $next($request);
}
private function logout(Request $request)
{
$request->session()->forget('nanicas');
Auth::logout();
$request->session()->invalidate();
return $request->expectsJson()
? response()->json(['message' => 'Token expirado'], 401)
: redirect()->route('login');
}
}
我在 HOME 路由上使用这个中间件,如下所示:
Route::middleware('auth.nanicas')->group(function () {
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
});
我的 Laravel 会话持续两天,但我用于向外部 API 进行身份验证的内部令牌每两个小时就会过期。当令牌过期并且我刷新主屏幕时,会话将保留旧值而不是新更新的值。仅当我使用
$request->session()->regenerate()
时才会发生这种情况。如果我删除这一行,一切都会按预期进行。
根据Laravel文档,
regenerate()
用于重新生成会话ID。但是,文档没有解释这对应用程序的影响。
任何人都可以解释为什么当我使用
regenerate()
时会话没有使用新值更新?另外,我注意到注释掉网络组中的 \App\Http\Middleware\EncryptCookies::class
中间件会生成一些随机 ID。这可能与问题有关吗?
我决定使用类:
dd()
并默默地进行注册表,而不是使用任何像 var_dump
、Illuminate\Support\Facades\Log
或会弄脏屏幕或停止我的应用程序以进行调试的方法,从而获得预期的结果。
注意:我继续使用
$request->session()->regenerate();
,会话正在“重新生成”,我的用户继续登录,就好像什么也没发生一样。
[2024-04-12 13:20:58] local.ALERT: {"before":"kgZAcuh9vMPGxtuZCboKTGrbqLGPnwVaCZW0yuMT"}
[2024-04-12 13:20:58] local.ALERT: {"after":"kyoN8Jn679Vg26iubIfzGTcucS5e2uILtdbFDDBi"}
[2024-04-12 13:21:22] local.ALERT: {"before":"kyoN8Jn679Vg26iubIfzGTcucS5e2uILtdbFDDBi"}
[2024-04-12 13:21:23] local.ALERT: {"after":"iuZXh6PPzx0KyCXuCKynBxLb5SqxuZDDkpFsYAPc"}
[2024-04-12 13:21:29] local.ALERT: {"before":"iuZXh6PPzx0KyCXuCKynBxLb5SqxuZDDkpFsYAPc"}
[2024-04-12 13:21:30] local.ALERT: {"after":"1OvaFxmwzR2YO1d9NCKSHqFwhD7Nw1phIBUNpRY2"}
[2024-04-12 13:21:34] local.ALERT: {"before":"1OvaFxmwzR2YO1d9NCKSHqFwhD7Nw1phIBUNpRY2"}
[2024-04-12 13:21:35] local.ALERT: {"after":"CP3OStFiPwl4SaHLlig6nkei1VOexrWOt1HHygse"}
请注意,“after”键的值将始终等于下一个块的“before”键的值。
现在我问你,为什么调试结果弄脏屏幕会影响 set-cookie 或 Laravel 对浏览器关于会话持久性的响应方式?