在 Laravel 5.2 中验证授权
Validate Authorization in Laravel 5.2
我的角色是动态的,他们的用户权限也是动态的。我有两种方法来验证用户是否有权访问特定页面。
方法一
class BaseController extends Controller
{
public function __construct() {
if(!\Auth::user()->IsPredefined) {
$result = $this->ValidateAuthorization();
if(!$result) {
\Auth::logout();
return redirect()->route("login");
}
}
}
private function ValidateAuthorization() {
$ActionName = \Route::getCurrentRoute()->getPath();
switch ($ActionName) {
case "ChangePassword":
$ModuleID = ModuleEnum::AccountManagemenet;
$ActionID = AccountActionEnum::ChangePassword;
return CheckUsePermissions($ModuleID, $ActionID);
}
}
private function CheckUsePermissions($ModuleID, $ActionID) {
$User = MySession::UserPermissions();
foreach($User->UserRolePermissions as $UserRolePermission) {
$CurrentActionID = $UserRolePermission->RolePermission->Permission->ActionID;
$CurrentModuleID = $UserRolePermission->RolePermission->Permission->ModuleID;
if($CurrentActionID == $ActionID && $CurrentModuleID == $ModuleID &&
$UserRolePermission->IsActive == true) {
return true;
}
}
return false;
}
}
方法二
在请求中使用 Authorize 方法class
public function authorize()
{
return true;
}
迷茫
- 如果方法 2 好,我是否应该为每个 Get、Put、Delete 和 POST 创建请求 class?
- 是否有更好的方法来验证授权?
你应该使用中间件并在路由中使用
Route::group(['middleware' => ['auth', 'admin']], function () { });
或者你可以在每个控制器构造函数中使用
public function __construct()
{
$this->middleware('auth');
$this->middleware('admin');
}
像
这样的管理中间件
class AdminAuthenticate
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check()) {
if (Auth::user()->IsPredefined) {
$result = $this->ValidateAuthorization();
if(!$result) {
return redirect('/logout');
}
}
}
return $next($request);
}
}
对于动态角色,我会这样做:
假设我有以下权限:
- 管理用户
- 管理 CMS
- 管理酒店
- 管理包
- 管理角色
现在 Super Admin
(显然拥有上述所有权限)可以创建一个角色,例如 Hotel Manager
并仅向 Manage Hotels
.
分配权限
现在的路线如下:
Route::get('/admin/hotels', 'HotelsController@index')->name('admin.hotels.index');
我会把它放在一个 Route Group
中,里面有一个中间件:
Route::group(['prefix' => '/admin/hotels', 'middleware' => ['permission:manage_hotels']], function () {
Route::get('/', 'HotelsController@index')->name('admin.hotels.index');
Route::post('/', 'HotelsController@create')->name('admin.hotels.create');
});
然后我会创建一个Permission
中间件:
class Permission
{
public function handle($request, Closure $next, $permission)
{
//if not super admin (super admin role_id is 1)
if(auth()->user()->role_id != 1) {
//explode extra param passed to this middleware (here manage_hotels)
$permission_array = explode('_', $permission);
foreach ($permission_array as $key => $value) {
$permission_array[$key] = ucfirst($value);
}
$permission_name = implode(' ', $permission_array);
$permitted = auth()->user()->role->permissions()->where('name', $permission_name)->first();
if(! $permitted) {
return redirect()->route('admin.dashboard')->withErrors(['error' => ['message' => 'You are not allowed to perform this action.']]);
}
}
return $next($request);
}
}
当然,您需要将这些路由包装到 Admin Middleware
中,这将确保用户已登录并具有管理员角色。
我的角色是动态的,他们的用户权限也是动态的。我有两种方法来验证用户是否有权访问特定页面。
方法一
class BaseController extends Controller
{
public function __construct() {
if(!\Auth::user()->IsPredefined) {
$result = $this->ValidateAuthorization();
if(!$result) {
\Auth::logout();
return redirect()->route("login");
}
}
}
private function ValidateAuthorization() {
$ActionName = \Route::getCurrentRoute()->getPath();
switch ($ActionName) {
case "ChangePassword":
$ModuleID = ModuleEnum::AccountManagemenet;
$ActionID = AccountActionEnum::ChangePassword;
return CheckUsePermissions($ModuleID, $ActionID);
}
}
private function CheckUsePermissions($ModuleID, $ActionID) {
$User = MySession::UserPermissions();
foreach($User->UserRolePermissions as $UserRolePermission) {
$CurrentActionID = $UserRolePermission->RolePermission->Permission->ActionID;
$CurrentModuleID = $UserRolePermission->RolePermission->Permission->ModuleID;
if($CurrentActionID == $ActionID && $CurrentModuleID == $ModuleID &&
$UserRolePermission->IsActive == true) {
return true;
}
}
return false;
}
}
方法二
在请求中使用 Authorize 方法class
public function authorize()
{
return true;
}
迷茫
- 如果方法 2 好,我是否应该为每个 Get、Put、Delete 和 POST 创建请求 class?
- 是否有更好的方法来验证授权?
你应该使用中间件并在路由中使用
Route::group(['middleware' => ['auth', 'admin']], function () { });
或者你可以在每个控制器构造函数中使用
public function __construct()
{
$this->middleware('auth');
$this->middleware('admin');
}
像
这样的管理中间件class AdminAuthenticate
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check()) {
if (Auth::user()->IsPredefined) {
$result = $this->ValidateAuthorization();
if(!$result) {
return redirect('/logout');
}
}
}
return $next($request);
}
}
对于动态角色,我会这样做:
假设我有以下权限:
- 管理用户
- 管理 CMS
- 管理酒店
- 管理包
- 管理角色
现在 Super Admin
(显然拥有上述所有权限)可以创建一个角色,例如 Hotel Manager
并仅向 Manage Hotels
.
现在的路线如下:
Route::get('/admin/hotels', 'HotelsController@index')->name('admin.hotels.index');
我会把它放在一个 Route Group
中,里面有一个中间件:
Route::group(['prefix' => '/admin/hotels', 'middleware' => ['permission:manage_hotels']], function () {
Route::get('/', 'HotelsController@index')->name('admin.hotels.index');
Route::post('/', 'HotelsController@create')->name('admin.hotels.create');
});
然后我会创建一个Permission
中间件:
class Permission
{
public function handle($request, Closure $next, $permission)
{
//if not super admin (super admin role_id is 1)
if(auth()->user()->role_id != 1) {
//explode extra param passed to this middleware (here manage_hotels)
$permission_array = explode('_', $permission);
foreach ($permission_array as $key => $value) {
$permission_array[$key] = ucfirst($value);
}
$permission_name = implode(' ', $permission_array);
$permitted = auth()->user()->role->permissions()->where('name', $permission_name)->first();
if(! $permitted) {
return redirect()->route('admin.dashboard')->withErrors(['error' => ['message' => 'You are not allowed to perform this action.']]);
}
}
return $next($request);
}
}
当然,您需要将这些路由包装到 Admin Middleware
中,这将确保用户已登录并具有管理员角色。