权限
建议编辑在 Orchid 中,访问控制是通过权限和角色来管理的。权限定义了访问权限,可以直接分配给用户或通过角色分配,从而简化访问管理。
通常,使用角色来分组权限会更好,因为这使得用户权限管理更简单。与其为每个用户分配单独的权限,不如通过角色为用户分配一个或多个角色。然而,如果需要,也可以直接将权限分配给用户。
重要提示: 权限并不替代 Laravel 的 Gate 或 Policies 机制。这些机制仍然是细粒度访问控制所必需的,权限与它们一起工作。
尽管角色简化了管理,重点应放在权限上。应用程序逻辑应基于权限而不是角色来检查访问,使用 can
方法。
重要提示: 访问应始终通过权限进行检查,而不是角色。角色只是用于分组权限的便利,访问应始终基于权限而不是角色进行检查。
用法
方法 hasAccess
将严格要求传递的权限有效以授予访问权限。
// 检查同时针对用户及其角色进行
Auth::user()->hasAccess($string);
方法 hasAnyAccess
将在任何权限通过检查时授予访问权限。
$user = User::find(1);
if ($user->hasAnyAccess(['user.admin', 'user.update'])) {
// 如果用户有权限,则执行此代码
}
注意。 可以使用通配符基于权限进行检查,使用
*
字符匹配任何权限集合。
$user = User::find(1);
if ($user->hasAccess('user.*')) {
// 如果用户有权限,则执行此代码
}
在少数情况下,您可能需要获取直接或通过角色拥有权限的用户。为此,您可以使用:
User::byAccess('platform.systems.users')->get();
// 或者如果用户至少有一个传递的权限
User::byAnyAccess([
'platform.systems.users',
'non existent',
])->get();
用户有多种管理角色的选项:
// 获取所有用户角色
Auth::user()->getRoles();
// 检查用户是否有角色
Auth::user()->inRole($role);
// 为用户添加角色
Auth::user()->addRole($role);
角色
角色也有以下程序:
// 返回具有此角色的所有用户。
$role->getUsers();
注册权限
您可以在应用程序中注册权限以管理对特定功能的访问。
使用提供者注册权限的示例:
use Orchid\Platform\ItemPermission;
use Orchid\Platform\OrchidServiceProvider;
class PermissionServiceProvider extends OrchidServiceProvider
{
/**
* 为应用程序注册权限。
*
* @return ItemPermission[]
*/
public function permissions(): array
{
return [
ItemPermission::group('modules')
->addPermission('analytics', '访问数据分析')
->addPermission('monitor', '访问系统监控'),
];
}
}
屏幕中的检查
每个创建的屏幕已经使用方法 permission
设置了内置的权限检查,该方法接受数组和字符串值进行验证:
namespace App\Orchid\Screens;
use Orchid\Screen\Screen;
class History extends Screen
{
/**
* 访问此屏幕所需的权限。
*/
public function permission(): ?iterable
{
return [
'systems.history'
];
}
// ...
}
如果列出了多个键,用户只要有至少一个权限就会被授予访问权限。
如果没有访问权限,将调用静态方法 unaccessed
,默认情况下将显示 403
错误。您可以重写此响应,例如重定向到支付页面或返回不同的响应:
use Illuminate\Http\RedirectResponse;
/**
* @return \Illuminate\Http\RedirectResponse
*/
public static function unaccessed(): RedirectResponse
{
return redirect('/other-screen');
}
中间件中的检查
小型应用程序可能不需要为每个屏幕或类定义权限,而是检查它们在路由中的可用性。
为此,在 app/Http/Kernel
中注册一个新的 middleware
:
/**
* 应用程序的路由中间件。
*
* 这些中间件可以分配给组或单独使用。
*
* @var array
*/
protected $routeMiddleware = [
//...
'access' => \Orchid\Platform\Http\Middleware\Access::class,
];
之后,可以将其用于任何路由定义,通过传递参数 access:my-permission
,就像在 Auth::user()->hasAccess($string);
中一样。
Route::screen('/stories', StoriesScreen::class)
->middleware('access:systems.history');
您还可以将它们分组到组中:
Route::middleware(['access:systems.history'])->group(function () {
Route::screen('/stories', StoriesScreen::class);
Route::get('/stories/best', function () {
// ...
});
});
Blade 中的检查
对于依赖于 Blade 模板渲染的应用程序,可以方便地添加“自定义 If 语句”如下:
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Auth;
/**
* 启动任何应用程序服务。
*
* @return void
*/
public function boot()
{
Blade::if('hasAccess', function (string $value) {
$user = Auth::user();
if ($user === null) {
return false;
}
return $user->hasAccess($value);
});
}
一旦定义了自定义条件,您可以在模板中使用它:
@hasAccess('platform.index')
<!-- 用户有 'platform.index' 操作的权限 -->
@elsehasAccess('platform.other')
<!-- 用户没有 'platform.index' 的权限,
但有 'platform.other' 的权限 -->
@else
<!-- 用户没有 'platform.index'
和 'platform.other' 的权限 -->
@endhasAccess
@unlesshasAccess('platform.index')
<!-- 用户没有 'platform.index' 的权限 -->
@endhasAccess
通过控制台创建管理员用户
要创建具有最大(在创建时)权限的用户,请运行以下命令:
php artisan orchid:admin
要为现有用户授予最大权限,请使用 --id
选项运行:
php artisan orchid:admin --id=1
如果您为用户添加了新的必填列并需要修改命令以添加相应的值,请首先通过在服务提供者中添加以下代码指定 Orchid 使用您的模型:
use Orchid\Support\Facades\Dashboard;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Dashboard::useModel(
\Orchid\Platform\Models\User::class,
\App\Models\User::class
);
}
}
然后在您的 User
模型中重写 createAdmin
方法:
public static function createAdmin(string $name, string $email, string $password): void
{
throw_if(static::where('email', $email)->exists(), '用户已存在');
static::create([
'name' => $name,
'email' => $email,
'password' => Hash::make($password),
'permissions' => Dashboard::getAllowAllPermission(),
]);
}
现在您可以根据需要修改此方法,并在执行创建命令时将执行此方法。
用户模拟
Orchid\Access\Impersonation
类为开发人员提供了方便的功能,可以以其他用户身份登录。
它允许管理员模拟其他用户,以便查看和执行他们的操作。
这对于解决用户报告的问题非常有用。
要切换到其他用户,请使用 loginAs()
方法:
use Orchid\Access\Impersonation;
// 以其他用户身份登录
Impersonation::loginAs($otherUser);
要返回到原始用户,请调用 logout()
方法:
// 返回到原始用户
Impersonation::logout();
isImpersonating()
方法检查是否已进行模拟:
if (Impersonation::isImpersonating()) {
// 用户正在模拟其他用户
}
impersonator()
方法返回有关原始用户的信息。如果没有进行模拟,该方法将返回 null
:
// 获取有关原始用户的信息
$impersonator = Impersonation::impersonator();