【问题标题】:how to assign a hasMany role check in Laravel如何在 Laravel 中分配 hasMany 角色检查
【发布时间】:2016-06-20 11:43:19
【问题描述】:

在我的网站上

我有一个看起来像 thi 的 InitiatorController

class InitiatorController extends Controller
{

 use ExchangerateTrait;
 public function __construct(){

    $this->middleware('auth');
    $this->middleware('role:sales'); // replace 'collector' with whatever role you need.
}

 public function getIndex(){


            return redirect('initiator/home');
 }

}

现在验证后,我正在检查用户角色是否为 sales 或不在 Role middleware 。

我的角色中间件是这样的。

class Role
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
        public function handle($request, Closure $next, $role){

            if ($request->user()->role != $role){

                    if($role=="collector" || $role=="admin" )
                    return Redirect::to('/');  
                    if($role=="director" || $role=="admin" )
                    return Redirect::to('/');  
                    if($role=="admin1" || $role=="admin" )
                    return Redirect::to('/');
                    if($role=="admin2" || $role=="admin" )
                    return Redirect::to('/');
                    if($role=="sales" || $role=="admin" )
                     return Redirect::to('/');
                    if($role=="developer" || $role=="admin" )
                     return Redirect::to('/');


            }

            return $next($request);
        }

}

现在我的角色是director,但他也是一名销售人员,我该如何解决这个问题。

第一个想法 在控制器中

如果我知道如何将一组角色发送到类似这样的中间件

$roles = array('director,sales,teamlead');
$this->middleware('role:$roles');

然后在中间件中我可以像这样检查

if(in_array ($request->user()->role,$roles)){
      //do some thing
}
else
{
   //redirect to login 
}

【问题讨论】:

  • 你的意思是如何在中间件中获取多个角色?
  • @Chay22 是的类似的东西,假设在 Initiator 控制器中有一些功能只能由也是销售人员的团队负责人访问,我该如何检查?

标签: php laravel-5.1


【解决方案1】:

这就是我实现角色中间件的方式:

RoleMiddleware.php

class RoleMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $routeRoles = $this->getRolesForRoute($request->route());
        $user = $request->user();
        if (!$routeRoles || (isset($user) && $user->isPermitted($routeRoles))) {
            return $next($request);
        }
        abort(401);
    }

    /**
     * Function to get the roles of the requested route.
     * 
     * @param \Illuminate\Routing\Route $route
     * @return array|null
     */
    public function getRolesForRoute($route)
    {
        $routeAction = $route->getAction();
        return isset($routeAction['roles']) ? $routeAction['roles'] : null;
    }
}

routes.php

Route::get(
            '/post/delete/{pageId}',
            [
                'as' => 'deleteNavigation',
                'uses' => 'NavigationController@postDeleteNavigation',
                'roles' => 'Administrator'
            ]
        );

注意“角色”可以是数组或字符串

然后在User.php中的用户雄辩模型:

/**
 * Function to check whether this user is permitted
 * a route or not.
 *
 * @param array|string|null $routeRoles Route roles.
 *
 * @return bool
 */
public function isPermitted($routeRoles)
{
    $routeRoles = strtolower($routeRoles);
    if (empty($routeRoles)) {
        return true;
    }

    $userRole = strtolower($this->role()->getResults()->name);
    if (is_array($routeRoles)) {
        foreach ($routeRoles as $routeRole) {
            if ($routeRole == $userRole) {
                return true;
            }
        }
    } else {
        if ($routeRoles == $userRole) {
            return true;
        }
    }

    return false;
}

/**
 * Define an inverse one-to-many relationship.
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 */
public function role()
{
    return $this->belongsTo(Role::class);
}

我知道这与您的逻辑略有不同,但对我来说效果很好。希望对您有所帮助。

【讨论】:

    【解决方案2】:

    我用的是 L5.2,但我认为它们之间没有区别。如果我正确理解您的问题,您可以插入多个中间件参数,就像

    $this->middleware('role:sales,leader'); //so on separated by commas
    

    以防万一您使用的是 PHP >= 5.6,它具有我经常使用的新功能:Variable-length argument list...$roles

    对于 5.6 以下,我猜func_get_args 可能也有帮助

    然后是中间件中的一些东西(也适应了我自己损坏的逻辑路由中间件)

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  array  $roles
     * @return mixed
     */
    public function handle($request, Closure $next, ...$roles)
    {
        $user = $request->user();
    
        if ($user && $this->isAllowed($user, $roles)) {
            return $next($request);
        }
    
        return view('errors.403');
    }
    

    继续查看我的逻辑错误

    /**
     * Check if current user role is allowed 
     * 
     * @param  string      $user    current requested user
     * @param  null|array  $roles
     * @return bool
     */
    protected function isAllowed($user, $roles)
    {
        $roles = $this->extractRoles($roles);
    
        //Check for role exsistance
        if (! $this->roleExists($roles)) {
            return false;
        }
    
        //Override this check if user has super privillege
        if ($user->role === $this->superRole()) {
            return true;
        }
    
        foreach ($roles as $role) {
            if (str_contains($role, $user->role)) {
                return true;
            }  
        }
    
        return false;
    }
    
    /**
     * Convert given roles to an array
     * 
     * @param  null|array  $roles
     * @return array
     */
    protected function extractRoles($roles)
    {
        $super = $this->superRole();
        foreach($roles as &$role)
            $roles = strtolower($role);
    
        //if no argument set on middleware return
        //the super role
        return count($roles) == 0 ? [$super] : $roles;
    }
    
    /**
     * Check if role is defined in config file
     * 
     * @param  null|array  $roles
     * @return bool
     */
    protected function roleExists($roles)
    {
        $roleList = config('roles.roles');
        foreach($roleList as &$role)
            $roleList = strtolower($role);
    
        foreach ($roles as $role) {
            if (in_array($roles, $roleList)) {
                return true;
            }
        }
    
        return false;
    }
    
    /**
     * Set the super privillege role
     * 
     * @return string 
     */
    public function superRole()
    {
        $super = config('roles.super');
    
        if (is_array($super)) {
            $super = head($super);
        }
    
        return (string) strtolower($super);
    }
    

    【讨论】:

    • 这是在控制器级别的权利,就像这个控制器可以被某些角色访问,但是我如何限制每个功能的权限,就像某些功能必须由某些角色访问一样
    • 我把那个和Policies(门的东西)分开只是为了让我的代码更干净(至少对我来说XD)
    • 我需要维护一个带有函数名和 id 的数据库吗?谁可以访问它们
    • 是的,我的经理正在谈论政策,但总的来说他不懂编码,所以他无法解释我应该如何设计
    • matt stauffer's blog 解释 ACL,它首先教会了我这些东西。很难列出每个控制器方法的能力,所以我也使用模型,而不仅仅是策略。
    【解决方案3】:

    您可以将模型中的关系定义为函数,并使用该函数检查 hasMany 角色。

    如 laravel 5 文档所示

    https://laravel.com/docs/5.2/eloquent-relationships#one-to-many

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-28
      • 2023-02-14
      • 2014-04-04
      • 2016-08-28
      相关资源
      最近更新 更多