服务提供商期间未调用授权门
Authorization gate not called during service provider
我在 AuthServiceProvider
中定义了一个 admin
门,用于向某些模型添加全局查询范围。假设我有模型 A
,由 Observer
(在 AppServiceProvider
中注册)观察,以及 B
,利用 admin
门添加全局查询范围。
// app/Providers/AuthServiceProvider.php
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Gate::define('admin', [static::class, 'admin']);
}
public static function admin(User $user): bool
{
return $user->group->name === 'Admin';
}
}
// app/B.php
class B extends Eloquent
{
public static function boot()
{
parent::boot();
if (!Gate::allows('admin')) {
static::addGlobalScope('public', function ($query) {
$query->where('public', true);
});
}
}
}
到目前为止一切正常。然后我添加了一个模型 C
,它有一个 Observer
并使用 admin
门。由于 C::observe()
触发 C::boot()
并且 AppServiceProvider
在 AuthServiceProvider
之前注册,门未定义,我将 Observer
注册提取到新的 ObserverServiceProvider
在 AuthServiceProvider
.
之后注册
// app/C.php
class C extends Eloquent
{
public static function boot()
{
parent::boot();
if (!Gate::allows('admin')) {
static::addGlobalScope('public', function ($query) {
$query->where('public', true);
});
}
}
}
// app/Providers/ObserverServiceProvider.php
class ObserverServiceProvider extends ServiceProvider
{
public function boot()
{
A::observe(AObserver::class);
C::observe(CObserver::class);
}
}
// config/app.php
'providers' => [
//...
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
//...
App\Providers\ObserverServiceProvider::class,
]
我的问题:
A
和 C
的观察者以及 B
的 boot()
方法中的 admin
门仍在工作,但是 Gate::allows('admin')
in C
始终 returns false
甚至不调用门函数。
在 C::boot()
中添加一个 var_dump(Gate::has('admin'))
输出 true
并稍后在同一请求中的 View
中使用 @can('admin')
也可以正常工作,因此门已明确定义并在原则上工作。
无法调用授权门,因为会话数据(以及经过身份验证的用户)由 StartSession
中间件提供,该中间件在服务提供商之后运行。
问题可以通过将Gate::allows()
检查放在匿名函数中来解决,因此它只在构建查询时执行:
// app/C.php
class C extends Eloquent
{
public static function boot()
{
parent::boot();
static::addGlobalScope('public', function ($query) {
if (!Gate::allows('admin')) {
$query->where('public', true);
}
});
}
}
我在 AuthServiceProvider
中定义了一个 admin
门,用于向某些模型添加全局查询范围。假设我有模型 A
,由 Observer
(在 AppServiceProvider
中注册)观察,以及 B
,利用 admin
门添加全局查询范围。
// app/Providers/AuthServiceProvider.php
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Gate::define('admin', [static::class, 'admin']);
}
public static function admin(User $user): bool
{
return $user->group->name === 'Admin';
}
}
// app/B.php
class B extends Eloquent
{
public static function boot()
{
parent::boot();
if (!Gate::allows('admin')) {
static::addGlobalScope('public', function ($query) {
$query->where('public', true);
});
}
}
}
到目前为止一切正常。然后我添加了一个模型 C
,它有一个 Observer
并使用 admin
门。由于 C::observe()
触发 C::boot()
并且 AppServiceProvider
在 AuthServiceProvider
之前注册,门未定义,我将 Observer
注册提取到新的 ObserverServiceProvider
在 AuthServiceProvider
.
// app/C.php
class C extends Eloquent
{
public static function boot()
{
parent::boot();
if (!Gate::allows('admin')) {
static::addGlobalScope('public', function ($query) {
$query->where('public', true);
});
}
}
}
// app/Providers/ObserverServiceProvider.php
class ObserverServiceProvider extends ServiceProvider
{
public function boot()
{
A::observe(AObserver::class);
C::observe(CObserver::class);
}
}
// config/app.php
'providers' => [
//...
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
//...
App\Providers\ObserverServiceProvider::class,
]
我的问题:
A
和 C
的观察者以及 B
的 boot()
方法中的 admin
门仍在工作,但是 Gate::allows('admin')
in C
始终 returns false
甚至不调用门函数。
在 C::boot()
中添加一个 var_dump(Gate::has('admin'))
输出 true
并稍后在同一请求中的 View
中使用 @can('admin')
也可以正常工作,因此门已明确定义并在原则上工作。
无法调用授权门,因为会话数据(以及经过身份验证的用户)由 StartSession
中间件提供,该中间件在服务提供商之后运行。
问题可以通过将Gate::allows()
检查放在匿名函数中来解决,因此它只在构建查询时执行:
// app/C.php
class C extends Eloquent
{
public static function boot()
{
parent::boot();
static::addGlobalScope('public', function ($query) {
if (!Gate::allows('admin')) {
$query->where('public', true);
}
});
}
}