Laravel 8 中路由文件中使用中间件方法失败的原因是什么?
What causes this failure to use a middleware method in the routes file, in Laravel 8?
我正在开发具有用户、角色和权限的 Laravel 8 应用程序。我使用 Microsoft Azure 进行用户登录。
我开始在他们的网站上关注 this tutorial。
我从 permissions
MySQL table 中获得了针对每个用户角色的 逗号分隔用户权限 列表。
我希望当前用户可以访问某些路由,具体取决于他们拥有的权限。
我将 userPermissions
变量存储在这样的会话中:
public function storeTokens($accessToken, $user, $user_role, $user_permissions) {
session([
'accessToken' => $accessToken->getToken(),
'refreshToken' => $accessToken->getRefreshToken(),
'tokenExpires' => $accessToken->getExpires(),
'userName' => $user->getDisplayName(),
'firstName' => $user->getGivenName(),
'lastName' => $user->getSurname(),
'userRole' => $user_role,
'userPermissions' => $user_permissions,
'userEmail' => null !== $user->getMail() ? $user->getMail() : $user->getUserPrincipalName(),
'userTimeZone' => $user->getMailboxSettings()->getTimeZone()
]);
}
我创建了一个新的中间件,叫做 CheckUserPermissions
:
class CheckUserPermissions
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
private $permission;
// Permissions checker
public function hasPermissionTo($permission) {
return in_array($permission, session('userPermissions'));
}
public function handle(Request $request, Closure $next)
{
// Check user permissions
if (!$this->hasPermissionTo($this->permission)) {
return redirect('/')->with('error', 'You do not have permission to access to this section of the application');
}
return $next($request);
}
}
我在app\Http\Kernel.php
注册了上面的中间件:
protected $routeMiddleware = [
//More middleware
'checkSignedIn' => \App\Http\Middleware\CheckSignedIn::class,
'checkUserPermissions' => \App\Http\Middleware\CheckUserPermissions::class,
];
问题
问题是我无法在控制器外使用policy/gate(即使当前用户有查看用户的权限)。
在 routes\web.php
中执行 Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions')->hasPermissionTo('view-users')
不起作用:
// Dashboard routes
Route::group(['prefix' => 'dashboard', 'middleware' => ['checkSignedIn']], function() {
Route::get('/', [DashboardContoller::class, 'index'])->name('dashboard');
Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions')->hasPermissionTo('view-users');
});
它导致在浏览器中显示 Method Illuminate\Routing\Route::hasPermissionTo does not exist
错误
我做错了什么?
您无法访问路由定义中的中间件方法。中间件只运行 handle
方法,因此您在编写代码时应牢记这一点。解决方法如下:
class CheckUserPermissions
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
private $permission;
// Permissions checker
public function hasPermissionTo($permission) {
return in_array($permission, session('userPermissions'));
}
public function handle(Request $request, Closure $next, ...$permissions)
{
// Check user permissions
foreach ($permissions as $permission) {
if (!$this->hasPermissionTo($permission)) {
return redirect('/')->with('error', 'You do not have permission to access to this section of the application');
}
}
return $next($request);
}
}
并将中间件用作:
Route::group(['prefix' => 'dashboard', 'middleware' => ['checkSignedIn']], function() {
Route::get('/', [DashboardContoller::class, 'index'])->name('dashboard');
Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions:view-users');
});
checkUserPermissions:view-users
中 :
之后的任何内容都作为 handle
方法的附加参数发送。您也可以发送多个:
Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions:view-users,see-users,glance-at-users');
逗号分隔列表中的每个项目都是中间件 $permissions
数组中的附加数组条目
我正在开发具有用户、角色和权限的 Laravel 8 应用程序。我使用 Microsoft Azure 进行用户登录。
我开始在他们的网站上关注 this tutorial。
我从 permissions
MySQL table 中获得了针对每个用户角色的 逗号分隔用户权限 列表。
我希望当前用户可以访问某些路由,具体取决于他们拥有的权限。
我将 userPermissions
变量存储在这样的会话中:
public function storeTokens($accessToken, $user, $user_role, $user_permissions) {
session([
'accessToken' => $accessToken->getToken(),
'refreshToken' => $accessToken->getRefreshToken(),
'tokenExpires' => $accessToken->getExpires(),
'userName' => $user->getDisplayName(),
'firstName' => $user->getGivenName(),
'lastName' => $user->getSurname(),
'userRole' => $user_role,
'userPermissions' => $user_permissions,
'userEmail' => null !== $user->getMail() ? $user->getMail() : $user->getUserPrincipalName(),
'userTimeZone' => $user->getMailboxSettings()->getTimeZone()
]);
}
我创建了一个新的中间件,叫做 CheckUserPermissions
:
class CheckUserPermissions
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
private $permission;
// Permissions checker
public function hasPermissionTo($permission) {
return in_array($permission, session('userPermissions'));
}
public function handle(Request $request, Closure $next)
{
// Check user permissions
if (!$this->hasPermissionTo($this->permission)) {
return redirect('/')->with('error', 'You do not have permission to access to this section of the application');
}
return $next($request);
}
}
我在app\Http\Kernel.php
注册了上面的中间件:
protected $routeMiddleware = [
//More middleware
'checkSignedIn' => \App\Http\Middleware\CheckSignedIn::class,
'checkUserPermissions' => \App\Http\Middleware\CheckUserPermissions::class,
];
问题
问题是我无法在控制器外使用policy/gate(即使当前用户有查看用户的权限)。
在 routes\web.php
中执行 Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions')->hasPermissionTo('view-users')
不起作用:
// Dashboard routes
Route::group(['prefix' => 'dashboard', 'middleware' => ['checkSignedIn']], function() {
Route::get('/', [DashboardContoller::class, 'index'])->name('dashboard');
Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions')->hasPermissionTo('view-users');
});
它导致在浏览器中显示 Method Illuminate\Routing\Route::hasPermissionTo does not exist
错误
我做错了什么?
您无法访问路由定义中的中间件方法。中间件只运行 handle
方法,因此您在编写代码时应牢记这一点。解决方法如下:
class CheckUserPermissions
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
private $permission;
// Permissions checker
public function hasPermissionTo($permission) {
return in_array($permission, session('userPermissions'));
}
public function handle(Request $request, Closure $next, ...$permissions)
{
// Check user permissions
foreach ($permissions as $permission) {
if (!$this->hasPermissionTo($permission)) {
return redirect('/')->with('error', 'You do not have permission to access to this section of the application');
}
}
return $next($request);
}
}
并将中间件用作:
Route::group(['prefix' => 'dashboard', 'middleware' => ['checkSignedIn']], function() {
Route::get('/', [DashboardContoller::class, 'index'])->name('dashboard');
Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions:view-users');
});
checkUserPermissions:view-users
中 :
之后的任何内容都作为 handle
方法的附加参数发送。您也可以发送多个:
Route::get('/users', [UsersContoller::class, 'index'])->middleware('checkUserPermissions:view-users,see-users,glance-at-users');
逗号分隔列表中的每个项目都是中间件 $permissions
数组中的附加数组条目