Home > PHP Framework > Laravel > body text

Implementation of ACL user authorization and permission checking functions in Laravel 5.1 framework

不言
Release: 2018-07-31 11:48:45
Original
2325 people have browsed it

The content of this article is about the implementation of ACL user authorization and permission checking functions in the Laravel 5.1 framework. It has certain reference value and I hope it can help friends in need.

1. Introduction

The out-of-the-box authentication function provided by Laravel makes user registration, login, logout and password reset convenient and simple.

But if you need to control access to specific parts of the site, or allow non-administrators to open/close specific pages, or ensure that certain users can only edit things they publish (such as articles), then you need to introduce Use a tool like BeatSwitch Lock or manually write such a function yourself. We call such a feature ACL: Access Control Lists (Access Control Lists), which are used to define a user's permissions to operate or view specific things based on their user record attributes.

Fortunately, starting from Laravel 5.1.11, Laravel provides out-of-the-box authorization functions to achieve the above requirements. We no longer need to do any additional work, just use it.

Note: Before starting this section, please refer to the upgrade guide to upgrade Laravel to Laravel 5.1.11, otherwise related functions will not be implemented.

2. What can be done?

The out-of-the-box ACL provided by Laravel is called Gate (this is not a product name like Spark, but just the name of a class and facade).

Using the Gate class (injection or using the Gate facade) allows us to easily check whether a certain user (currently logged in user or specified user) is allowed to operate specific things. The check code is as follows:

if (Gate::denies('update-post', $post)) {
    abort(403);
}
Copy after login

Put this code in the controller, it will use the defined rule update-post to check whether the currently authenticated user has permission to update the specified article.

You can also use Gate::allows, which is the opposite of the denies method, and can also be used through @can in the Blade view template, and there are many more, let's take a look next.

3. How to use?

Laravel ACL is built on the concept of "permissions". Permissions include a key (such as update-post) and a closure that returns true or false (parameters can be passed in).

3.1 Define permissions

Let us define the user update post permission update-post in AuthServiceProvider as follows:

<?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;
        });
    }
}
Copy after login

As you can see, The first parameter that defines the permission closure is the specified user. If the current user does not pass login authentication, Gate will return false by itself.

Of course, in addition to closures, you can also replace closures with class methods as the second parameter, which will be parsed in the container:

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

3.2 Check permissions through the Gate facade

Gate provides the following methods to check permissions: check, The functions of allows and denies, check and allows are exactly the same, while the functions of denies and allows are opposite.

If you use the facade to check permissions, you do not need to pass the user instance. The Gate facade will automatically pass in the current user:

if (Gate::denies(&#39;update-post&#39;, $post)) {       
    abort(403);
}
Copy after login

If you define multiple parameters in the permissions:

Gate::define(&#39;delete-comment&#39;, function ($user, $post, $comment) {
    //
});
Copy after login

The checking method is as follows:

if (Gate::allows(&#39;delete-comment&#39;, [$post, $comment])) {
    //
}
Copy after login

If you want to check whether a non-currently authenticated user has permission to operate, the calling method is as follows:

if (Gate::forUser($user)->allows(&#39;update-post&#39;, $post)) {
    //
}
Copy after login

3.3 Use Gate injection to check permissions

As always, you can inject the Gate class instead of using its facade. The injected class is the same as you in the AuthServiceProvider - Illuminate\Contracts\Auth\Access\Gate:

public function somethingResolvedFromContainer(Gate $gate)
{
    if ($gate->denies(&#39;update-post&#39;)) {
        // etc.
    }
}
Copy after login

3.4 Use the User model to check permissions

Laravel's App\User model now uses the Authorizabletrait, so you can use the can and cannot methods it provides, which correspond to the Gate's allows and denies methods respectively.

So we can also use the User model to check permissions:

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

3.5 Check permissions in Blade

You can use @can in Blade Command to check permissions:

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

The opposite is the @else command:

@can(&#39;update-post&#39;, $post)
    <!-- The Current User Can Update The Post -->
@else
    <!-- The Current User Can&#39;t Update The Post -->
@endcan
Copy after login

3.6 Abort permission check

If you are an administrator or super What if the user has all permissions? Or what if you want to temporarily switch the ACL logic for users?

The before method provided by Gate allows you to return before performing other checks under certain circumstances, without further checking permissions:

$gate->before(function ($user, $ability) {
    if ($user->last_name === &#39;Stauffer&#39;) {
        return true;
    }
});
Copy after login

Or when using the user's own:

$gate->before(function ($user, $ability) {
    if ($user->isOwner()) {
        return true;
    }
});
Copy after login

3.7 Policy class

As application logic becomes more and more complex, more and more permissions need to be processed. It is obviously not a wise idea to define all permissions in AuthServiceProvider. Therefore, Laravel introduced strategy classes. Strategy classes are some native PHP classes. Similar to how controllers group routes based on resources, strategy classes manage permissions in groups based on resources.

Generate policy class

You can use the following Artisan command to generate the PostPolicy policy class:

php artisan make:policy PostPolicy
Copy after login

The generated policy class is located in the app/Policies directory.

Then we can register the policy class in the policies attribute of AuthServiceProvider:

protected $policies = [
    Post::class => PostPolicy::class,
];
Copy after login

Below we edit the PostPolicy as follows:

<?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;
    }
}
Copy after login

Note: All policy classes are parsed through the service container , which means you can type-hint any dependencies in the constructor of your strategy class and they will be automatically injected.

Check Strategy

如果为某个资源类型定义了策略类,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);
        }
        // 更新文章...
    }
}
Copy after login

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

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

if (policy($post)->update($user, $post)) {
    //
}
Copy after login

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);
        // 更新文章...
    }
}
Copy after login

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

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

public function update($id){
    $post = Post::findOrFail($id);
    $this->authorize($post);
    // 更新文章...
}
Copy after login

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

$this->authorizeForUser($user, &#39;update&#39;, $post);
Copy after login

相关文章推荐:

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

相关课程推荐:

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

The above is the detailed content of Implementation of ACL user authorization and permission checking functions in Laravel 5.1 framework. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!