Policy 授权验证方法中无法获取对应模型实例?

今天在使用Policy做授权验证时,遇到了个坑,在使用中间件的方式来使用策略时,授权动作的方法中不能获取到路由隐式绑定的模型实例,不知道大家有没有遇到过?

这是注册的路由:

Policy 授权验证方法中无法获取对应模型实例?

在AuthServiceProvider中注册Policy:

注册中间件 Policy,模型绑定失效?

控制器中调用中间件:

注册中间件 Policy,模型绑定失效?

Policy show方法策略:

注册中间件 Policy,模型绑定失效?

控制器show方法:

Policy 授权验证方法中无法获取对应模型实例?

然后请求show方法,提示403 unauthorized 。。。

注册中间件 Policy,模型绑定失效?

试了下在策略类中__construct方法和before方法中记录日志,结果根本就没执行
然后我试了下不需要模型实例的写法,把中间件改成了can:show,App\Models\Nanny,策略show方法中只接受第一个参数,就可以正常运行,返回模型数据

注册中间件 Policy,模型绑定失效?

难道手册中说的路由隐式绑定没有生效嘛?

注册中间件 Policy,模型绑定失效?

然后又试了下不使用中间件的方式:

注册中间件 Policy,模型绑定失效?
控制器show方法:
注册中间件 Policy,模型绑定失效?
策略类show方法:
注册中间件 Policy,模型绑定失效?

可以正常返回数据:

注册中间件 Policy,模型绑定失效?
也能够正常打印出模型的id(能过获取模型实例)
注册中间件 Policy,模型绑定失效?

这是为什么啊,我就想使用中间件的方式来管理策略授权,现在无法实现路由的隐式绑定,咋办呢?

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

继续看了下手册,发现下面居然还有个authorizeResource方法来注册授权资源控制器
file
赶紧拿来试试,在控制器构造方法中使用这个方法:

$this->authorizeResource(Nanny::class, 'nanny');

这是此方法注册的路由中间件:
file
创建show方法对应的资源控制器中的策略方法:

    public function view(Authenticatable $user, Nanny $nanny) {
        dd($user->id, $nanny->id);
    }

控制器show方法:

    public function show(Request $request, Nanny $nanny)
    {
        return new NannyResource($nanny);
    }

调用接口,正常打印出用户和对应模型的id:
file
也是粗心,手册没看完就在开搞😄,然后看了哈authorizeResource方法的源码:
Laravel

就是帮我们注册了一些基本方法的策略中间件
第92行就很清楚了,需要在can中间件第一个参数传递策略动作,而第二个参数应该就是路由中的参数名或者对应模型类名
行吧,也算是加深了点印象

4年前 评论
讨论数量: 1

继续看了下手册,发现下面居然还有个authorizeResource方法来注册授权资源控制器
file
赶紧拿来试试,在控制器构造方法中使用这个方法:

$this->authorizeResource(Nanny::class, 'nanny');

这是此方法注册的路由中间件:
file
创建show方法对应的资源控制器中的策略方法:

    public function view(Authenticatable $user, Nanny $nanny) {
        dd($user->id, $nanny->id);
    }

控制器show方法:

    public function show(Request $request, Nanny $nanny)
    {
        return new NannyResource($nanny);
    }

调用接口,正常打印出用户和对应模型的id:
file
也是粗心,手册没看完就在开搞😄,然后看了哈authorizeResource方法的源码:
Laravel

就是帮我们注册了一些基本方法的策略中间件
第92行就很清楚了,需要在can中间件第一个参数传递策略动作,而第二个参数应该就是路由中的参数名或者对应模型类名
行吧,也算是加深了点印象

4年前 评论

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