#laravel #laravel-8
Вопрос:
У меня есть проект Laravel 8. Когда несколько запросов выполняются с использованием одного и того же сеанса одновременно, Auth::user()
возвращает null
некоторые запросы в моем поставщике услуг.
Например, при загрузке страницы и на стороне клиента с использованием AngularJS мы выполняем 3 одновременных запроса JSON для получения данных после onload
. 2 из 3 запросов JSON завершаются неудачно, потому что в моем поставщике услуг Authorization::user()
возвращается значение null.
- Во всех запросах идентификатор сеанса всегда правильный, проблема не в том, что информация о сеансе не предоставляется.
- В моем промежуточном программном обеспечении я вызываю
Authorization::user()
, который каждый раз успешно возвращает пользователя, включая все одновременные запросы. - В моем поставщике услуг при вызове
Authorization::user()
с несколькими одновременными запросами происходит сбой некоторых запросов.
Как мне исправить своего поставщика услуг?
Мой поставщик услуг
class MyServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('permissions', function() {
// we have already checked Auth::user() in middleware
// before getting here, this should never fail
// this fails 2 of 3 times when accessed simultaneously
// with same session
$u = Auth::user();
if (empty($u)) {
Log::error(__METHOD__, ['singleton' => 'permissions', 'error' => 'invalid_user']);
return new PermissionCache(0);
}
return new PermissionCache($u->employeeId);
});
}
}
Мой Класс Промежуточного программного обеспечения:
class MyApiMiddleware
{
public function handle($request, Closure $next)
{
// this always works for all requests
$u = Auth::user();
if (empty($u)) {
Log::error(__METHOD__, ['url' => $request->url(), 'session' => $request->session()->getId(), 'error' => 'user_invalid']);
return Response::json(ExceptionHelper::CreateToArray('invalidAuthorization'), 500);
}
// the following fails when it should be good
// because in MyServiceProvider, sometimes
// Auth::user() returns null even though
// above it worked perfectly, as it should
$p = App::make('permissions');
if (!$p->allowSomthing()) {
Log::error(__METHOD__, ['url' => $request->url(), 'session' => $request->session()->getId(), 'error' => 'permission_invalid']);
return Response::json(ExceptionHelper::CreateToArray('invalidAuthorization'), 500);
}
}
}
My Middleware Declaration:
class Kernel extends HttpKernel
{
protected $middleware = [
// AppHttpMiddlewareTrustHosts::class,
AppHttpMiddlewareTrustProxies::class,
FruitcakeCorsHandleCors::class,
AppHttpMiddlewarePreventRequestsDuringMaintenance::class,
IlluminateFoundationHttpMiddlewareValidatePostSize::class,
AppHttpMiddlewareTrimStrings::class,
// IlluminateFoundationHttpMiddlewareConvertEmptyStringsToNull::class,
];
protected $middlewareGroups = [
'public' => [
// AppHttpMiddlewareEncryptCookies::class,
IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
IlluminateSessionMiddlewareStartSession::class,
IlluminateViewMiddlewareShareErrorsFromSession::class,
AppHttpMiddlewareVerifyCsrfToken::class,
IlluminateRoutingMiddlewareSubstituteBindings::class,
],
'session' => [
// AppHttpMiddlewareEncryptCookies::class,
IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
IlluminateSessionMiddlewareStartSession::class,
IlluminateViewMiddlewareShareErrorsFromSession::class,
AppHttpMiddlewareVerifyCsrfToken::class,
IlluminateRoutingMiddlewareSubstituteBindings::class,
MySessionMiddleware::class,
],
'api' => [
// AppHttpMiddlewareEncryptCookies::class,
IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class,
IlluminateSessionMiddlewareStartSession::class,
IlluminateViewMiddlewareShareErrorsFromSession::class,
IlluminateRoutingMiddlewareSubstituteBindings::class,
MyApiMiddleware::class,
],
];
}
Конфигурация сеанса, используемые значения по умолчанию:
return [
'driver' => env('SESSION_DRIVER', 'file'),
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => FALSE,
'encrypt' => FALSE,
'files' => storage_path('framework/sessions'),
'connection' => env('SESSION_CONNECTION', NULL),
'table' => 'sessions',
'store' => env('SESSION_STORE', NULL),
'lottery' => [2, 100],
'cookie' => env(
'SESSION_COOKIE',
Str::slug(env('APP_NAME', 'laravel'), '_') . '_session'
),
'path' => '/',
'domain' => env('SESSION_DOMAIN', NULL),
'secure' => env('SESSION_SECURE_COOKIE'),
'http_only' => TRUE,
'same_site' => 'lax',
];
Комментарии:
1. Задействованы ли токены CSRF? Возможно, это может быть проблемой (последующие запросы аннулируют предыдущие токены).
2. Нет, это не CSRF. Ошибка в прошлом.
Ответ №1:
Моя проблема заключалась в том, что я пытался получить значение сеанса/аутентификации в моей конструкции контроллера::__. Информация о сеансе в запросе при инициализации контроллера еще не загружена. Мои модульные тесты не уловили этого, потому что эта информация была высмеяна, и мой проект обновляется с laravel 4.2, в котором это работало.