关于 Laravel-permission 请求验证 如何统一验证?

官方 分别可以在中间件和控制器中调用 验证
那么假设 这里有两个权限
articles,edit articles 分别对应 列表 和 编辑
那么是不是 需要 配置路由
列表调用 验证中间件 'middleware' => ['permission: articles']
编辑调用 编辑中间件 'middleware' => ['permission:edit articles']
如果在控制器构造方法验证 可能就是要判断请求的方法来分别使用对应的中间件

这样很麻烦

然后考虑统一中间件写一个规则
对于权限名称 列表、编辑 修改成articles/index,articles/edit
然后通过统一中间件
获取 ( 访问路径 | 控制器/方法 ) 名称,然后用名称来判断 用户是不是有这个权限
目前这种方式可行

但是判断restful就不行了
get /articles
post /articles
就无法区分了

这里有几个问题:
写一个统一的中间件来判断,使用permission的名称去对应是否正确?
如果对应是 对应到 访问路径还是控制器/方法

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 6
JaguarJack
list($controller, $action) = explode('@', $route['uses']);  
$controller = str_ireplace('controller', '', @array_pop(explode('\\', $controller)));     
return sprintf('%s@%s', strtolower($controller), strtolower($action));

目前想到的只有这么做了

5年前 评论
<?php

namespace App\Http\Middleware;

use Closure;
use Gate;
use Illuminate\Http\Request;

class Authorize
{
    public function handle(Request $request, Closure $next)
    {
        if (app()->environment('local') || user()->hasRole('SuperAdmin')) {
            return $next($request);
        }

        $route = $request->route();
        $action = $route->getAction();

        $action = array_add($action, 'controller', $action['uses']);

        list($class, $method) = array_pad(explode('@', $action['controller'], 2), 2, '');

        $policyClass = str_replace('App\\Http\Controllers', 'App\\Policies', $class) . 'Policy';

        if (class_exists($policyClass)) {
            Gate::policy($class, $policyClass);
            if (Gate::denies($method, $class)) {
                abort(403, '没有权限操作!');
            }
        }

        $route->setAction($action);

        return $next($request);
    }
}
<?php

namespace App\Policies;

use App\Models\User;

class UserControllerPolicy
{
    public function current()
    {
        return true;
    }

    public function currentPermissions()
    {
        return true;
    }

    public function userRoles(User $user)
    {
        return $user->can('user.assignRoles');
    }

    public function userPermissions(User $user)
    {
        return $user->can('user.assignPermissions');
    }

    public function __call($method, $args)
    {
        return user()->can('user.' . $method);
    }
}
5年前 评论

@JaguarJack
@yanthink
首先感谢各位的回复,这里看出大家都是比较倾向基于 控制器/方法粒度的权限控制,那么就有了一种情况,路由中直接回调函数返回的是无法验证控制的,或者说路由中不指向控制器/方法是不规范的

还一种想法就是基于 请求方式+请求path来做验证 也能限制请求权限控制的唯一性,但是定义上看着感觉不是很友好

期待更好的解决方式,同时想了解一下大家哪种方式是目前比较通用的解决方案

5年前 评论

@xiaohuazai 一般不用闭包路由吧

5年前 评论
JaguarJack

@xiaohuazai 这已经算是通用的了,颗粒度最小, 至于你说的闭包路由,会导致路由无法cache,建议放弃!

5年前 评论

@JaguarJack 好的 那我就选这样解决啦,函数我优化了一下

return ltrim($action['uses'], $action['namespace']); //外层可以再包裹strtolower
5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!