我有一个 Laravel 8 项目。当同时使用同一个会话发出多个请求时,\Auth::user()
会针对我的服务提供者中的某些请求返回 null
。
例如,当页面加载并在客户端使用 AngularJS 时,我们在 onload
之后同时发出 3 个 JSON 数据请求。 3 个 JSON 请求中有 2 个失败,因为在我的服务提供商中,\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);
}
}
}
我的中间件声明:
class Kernel extends HttpKernel
{
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
protected $middlewareGroups = [
'public' => [
// \App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'session' => [
// \App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
MySessionMiddleware::class,
],
'api' => [
// \App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::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',
];
答案 0 :(得分:0)
我的问题是我试图在我的控制器 ::__construct 中获取 session/auth 值。控制器初始化时请求中的会话信息尚未加载。我的单元测试没有发现这个,因为这个信息被嘲笑了,我的项目正在从 laravel 4.2 升级,这个版本起作用了。