代码之家  ›  专栏  ›  技术社区  ›  Jesse Orange

基于关系的Laravel中间件

  •  0
  • Jesse Orange  · 技术社区  · 6 年前

    在我的Laravel应用程序中,管理员可以被分配到工作中,我还有超级管理员可以做任何事情。

    让我们用一个粗略的路线来说明:

    http://localhost:3000/jobs/{job}

    http://localhost:3000/jobs/{job}/notes{note}

    在这种情况下 {job} 是通过路由模型绑定获得的id,并将注释附加到作业。

    分配给作业的管理员通过以下关系方法完成:

    /**
     * Get the jobs that this admin has access to via the pivot table
     *
     * @return void
     */
    public function jobs()
    {
        return $this->belongsToMany(JobPost::class, 'job_post_admin', 'admin_id', 'job_post_id');
    }
    

    所以我可以用 $user->jobs

    所以如果用户只能访问 http://localhost:3000/jobs/{1} 他们去了 http://localhost:3000/jobs/{2} 它们应该重新定向。

    我创建了一个名为Access的中间件

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (Auth::guard('admin')->user()) {
    
            $user = Auth::guard('admin')->user();
    
            if ($user->is_admin) {
                return $next($request);
            } else {
                if ($user->jobs->contains($job)) {
                    return $next($request);
                } else {
                    return response('You do not have sufficient priveledges to perform this action.', 403);
                }
            }
        } else {
            return redirect()->back();
        }
    }
    

    但是,我很困惑如何从URL中获取作业ID。

    我有一个工作的中间件,看起来像这样:

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use Auth;
    
    class Access
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            if (Auth::guard('admin')->user()) {
    
                $user = Auth::guard('admin')->user();
    
                $job = $request->vacancy;
    
                if ($user->is_admin) {
                    return $next($request);
                } else {
                    if ($user->jobs->contains($job)) {
                        return $next($request);
                    } else {
                        return response('You do not have sufficient priveledges to perform this action.', 403);
                    }
                }
            } else {
                return redirect()->back();
            }
        }
    }
    

    不过,我现在很感兴趣,因为我还没有真正承认Laravel中的授权,它比中间件有好处吗?

    1 回复  |  直到 6 年前
        1
  •  2
  •   apokryfos    6 年前

    身份验证不同于授权。拉威尔同时支持这两种方法。

    您可以使用授权策略执行您需要的操作,不需要额外的中间件。

    首先创建策略:

    php artisan make:policy JobsPolicy --model=Job
    

    这将成为你的样板。然后可以添加操作:

    class JobsPolicy {
        use HandlesAuthorization;
    
        //If you return true here the policy always succeeds
        public function before(User $user, $ability) { 
            if ($user->is_admin) {
                return true;
            }
        }
    
    
        public function view(User $user, Job $job) {
            return $user->jobs->contains($job);
        }
    
        public function create(User $user) {
            return true; //Return true if the user can create jobs
        }
    
        public function update(User $user, Job $job) {
              return $user->jobs->contains($job);
        }   
    }
    

    AuthServiceProvider $policies 数组:

     protected $policies = [
        Job::class => JobPolicy::class        
    ];
    

    然后您可以添加已经存在的中间件,例如:

    Routes::get('jobs/{job}/notes/{note}', ...)->middleware("can:view,job"); 
    

    这将确保当前经过身份验证的用户 can view 这个 job

    报告里有更多的信息 documentation