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

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

这样很麻烦

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

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

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

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 6
JaguarJack
list($controller, $action) = explode('@', $route['uses']);  
$controller = str_ireplace('controller', '', @array_pop(explode('\\', $controller)));     
return sprintf('%s@%s', strtolower($controller), strtolower($action));

目前想到的只有这么做了

1年前 评论
<?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);
    }
}
1年前 评论

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

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

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

1年前 评论

@xiaohuazai 一般不用闭包路由吧

1年前 评论
JaguarJack

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

1年前 评论

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

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

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!