Rumah > rangka kerja php > Laravel > Laravel 5.1框架中的ACL用户授权和权限检查功能的实现

Laravel 5.1框架中的ACL用户授权和权限检查功能的实现

不言
Lepaskan: 2018-07-31 11:48:45
asal
2421 orang telah melayarinya

本篇文章给大家分享的内容是关于Laravel 5.1框架中的ACL用户授权及权限检查功能的实现,有一定的参考价值,希望可以帮助到有需要的朋友。

1、引言

Laravel提供的开箱即用的认证功能使得用户注册、登录、退出和密码重置变得便捷和简单。

但是如果你需要控制访问站点特定部分,或者让非管理员打开/关闭特定页面,又或者确保某些用户只能编辑自己发布的东西(如文章),那么 你就需要引入类似BeatSwitch Lock这样的工具或者自己手动编写这样的功能。我们将这样的功能称之为ACL:Access Control Lists(访问控制列表),用于定义用户基于其用户记录属性操作或查看特定事物的权限。

幸运的是,从Laravel 5.1.11开始,Laravel提供了开箱即用的授权功能用于实现上述需求,我们不再需要做任何额外工作,用就是了。

注:在开始本节之前,请参考升级指南将Laravel升级到Laravel 5.1.11,否则不能实现相关功能。

2、能做什么?

Laravel提供的开箱即用的ACL被称作Gate(这并不是一个类似Spark的产品名称,而只是一个类和门面的名称)。

使用Gate类(注入或使用Gate门面)允许我们轻松检查某个用户(当前登录用户或指定用户)是否允许操作特定事物。检查代码如下:

if (Gate::denies('update-post', $post)) {
    abort(403);
}
Salin selepas log masuk

将这段代码放到控制器中,它将会使用定义好的规则update-post来检查当前认证用户是否有权限更新指定文章。

你还可以使用Gate::allows,该方法与denies方法相对,还可以在Blade视图模板中通过@can来使用,还有更多更多,让我们接下来一窥究竟。

3、如何使用?

Laravel ACL建立在“权限”概念之上,权限包括一个键(例如update-post)和一个返回true或false的闭包(可传入参数)。

3.1 定义权限

让我们在AuthServiceProvider中定义用户更新文章权限update-post如下:

<?php
namespace App\Providers;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider{
    /**
     * 注册应用所有的认证/授权服务.
     *
     * @param  \Illuminate\Contracts\Auth\Access\Gate  $gate
     * @return void
     */
    public function boot(GateContract $gate)
    {
        parent::registerPolicies($gate);
        $gate->define(&#39;update-post&#39;, function ($user, $post) {
            return $user->id === $post->user_id;
        });
    }
}
Salin selepas log masuk

正如你所看到的,定义权限闭包的第一个参数是指定用户,如果当前用户没有通过登录认证,Gate将会自定返回false。

当然,除了闭包之外,还可以通过类方法作为第二个参数来替代闭包,该类会在容器中解析:

$gate->define('update-post', 'PostPolicy@update');

3.2 通过Gate门面检查权限

Gate提供如下方法进行权限检查:check、allows和denies,check和allows功能用法完全一样,而denies和allows功能相反。

如果你使用门面检查权限,则不需要传递用户实例,Gate门面会自动将当前用户传递进来:

if (Gate::denies(&#39;update-post&#39;, $post)) {       
    abort(403);
}
Salin selepas log masuk

如果你在权限中定义了多个参数:

Gate::define(&#39;delete-comment&#39;, function ($user, $post, $comment) {
    //
});
Salin selepas log masuk

则检查方法如下:

if (Gate::allows(&#39;delete-comment&#39;, [$post, $comment])) {
    //
}
Salin selepas log masuk

如果你想检查非当前认证用户是否有权限操作,调用方法如下:

if (Gate::forUser($user)->allows(&#39;update-post&#39;, $post)) {
    //
}
Salin selepas log masuk

3.3 使用Gate注入检查权限

和以往一样,可以注入Gate类而不是使用其门面,注入的类和你在AuthServiceProvider中一样——Illuminate\Contracts\Auth\Access\Gate:

public function somethingResolvedFromContainer(Gate $gate)
{
    if ($gate->denies(&#39;update-post&#39;)) {
        // etc.
    }
}
Salin selepas log masuk

3.4 使用User模型检查权限

Laravel的App\User模型现在使用了Authorizabletrait,因此可以使用其提供的can和cannot方法,分别对应Gate的allows和denies方法。

所以我们也可以使用User模型来检查权限:

public function update(Request $request, $id)
{
    $post = Post::findOrFail($id);
    if ($request->user()->cannot(&#39;update-post&#39;, $post)) {
        abort(403);
    }
    // 更新文章...
}
Salin selepas log masuk

3.5 在Blade中检查权限

你可以在Blade中使用@can指令来检查权限:

<a href="/post/{{ $post->id }}">查看文章</a>
@can(&#39;update-post&#39;, $post)
    <a href="/post/{{ $post->id }}/edit">编辑文章</a>
@endcan
Salin selepas log masuk

与之相对的是@else指令:

@can(&#39;update-post&#39;, $post)
    <!-- The Current User Can Update The Post -->
@else
    <!-- The Current User Can&#39;t Update The Post -->
@endcan
Salin selepas log masuk

3.6 中止权限检查

如果是管理员或超级用户拥有所有权限怎么做?或者你想要为用户临时切换ACL逻辑又该当如何?

Gate提供的before方法允许你在一些特定情况下在执行其他检查前就返回,不再往下检查权限:

$gate->before(function ($user, $ability) {
    if ($user->last_name === &#39;Stauffer&#39;) {
        return true;
    }
});
Salin selepas log masuk

或者使用用户自己的时候:

$gate->before(function ($user, $ability) {
    if ($user->isOwner()) {
        return true;
    }
});
Salin selepas log masuk

3.7 策略类

随着应用逻辑越来越复杂,要处理的权限越来越多,将所有权限定义在AuthServiceProvider显然不是一个明智的做法,因此Laravel引入了策略类,策略类是一些原生的PHP类,和控制器基于资源对路由进行分组类似,策略类基于资源对权限进行分组管理。

生成策略类

可以使用如下Artisan命令生成PostPolicy策略类:

php artisan make:policy PostPolicy
Salin selepas log masuk

生成的策略类位于app/Policies目录。

然后我们可以在AuthServiceProvider的policies属性中注册策略类:

protected $policies = [
    Post::class => PostPolicy::class,
];
Salin selepas log masuk

下面我们编辑PostPolicy如下:

<?php
namespace App\Policies;
use App\User;
use App\Post;
class PostPolicy{
    /**
     * 判断给定文章是否可以被给定用户更新
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}
Salin selepas log masuk

注:所有策略类都通过服务容器进行解析,这意味着你可以在策略类的构造函数中类型提示任何依赖,它们将会自动被注入。

检查策略

如果为某个资源类型定义了策略类,Gate将会使用第一个参数来判断检查策略类上的哪个方法。

因此,要检查是否有权限更新某篇文章,只需要传入文章实例和update权限:

<?php
namespace App\Http\Controllers;
use Gate;
use App\User;
use App\Post;
use App\Http\Controllers\Controller;
class PostController extends Controller{
    /**
     * 更新给定文章
     *
     * @param  int  $id
     * @return Response
     */
    public function update($id)
    {
        $post = Post::findOrFail($id);
        if (Gate::denies(&#39;update&#39;, $post)) {
            abort(403);
        }
        // 更新文章...
    }
}
Salin selepas log masuk

当然也可以使用User模型和Blade指令检查权限。

此外,Laravel还提供了一个全局帮助函数policy来检查权限:

if (policy($post)->update($user, $post)) {
    //
}
Salin selepas log masuk

3.8 控制器授权

由于大多数授权都会在检查权限失败的情况下退出控制器方法,因此在控制器中检查权限有一条捷径(AuthorizesRequeststrait提供,该trait在基类控制器Controller中被使用):

<?php
namespace App\Http\Controllers;
use App\Post;
use App\Http\Controllers\Controller;
class PostController extends Controller{
    /**
     * 更新给定文章
     *
     * @param  int  $id
     * @return Response
     */
    public function update($id)
    {
        $post = Post::findOrFail($id);
        $this->authorize(&#39;update&#39;, $post);
        // 更新文章...
    }
}
Salin selepas log masuk

和我们上面的例子一样,如果授权失败会抛出403错误。

最后,如果你的控制器方法名和策略类中的方法名相同,例如都是update,则可以省略authorize的第一个参数:

public function update($id){
    $post = Post::findOrFail($id);
    $this->authorize($post);
    // 更新文章...
}
Salin selepas log masuk

此外,AuthorizesRequests也提供了对非当前认证用户权限检查的支持:

$this->authorizeForUser($user, &#39;update&#39;, $post);
Salin selepas log masuk

相关文章推荐:

Laravel 5.1框架中如何创建自定义Artisan控制台命令

相关课程推荐:

2017年最新的五个Laravel视频教程推荐

Atas ialah kandungan terperinci Laravel 5.1框架中的ACL用户授权和权限检查功能的实现. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan