Example of ACL User authorization and permission check in Laravel 5.1

Source: Internet
Author: User
Tags auth closure php class

1. Introduction
Laravel's out-of-the-box authentication feature makes it easy to register, log on, exit, and reset your password.

However, if you need to control access to specific parts of the site, or ask a non-administrator to open/close a specific page, or make sure that some users can only edit their own published content (such as articles ), then you need to introduce tools like BeatSwitch Lock or manually write such functions. We call this function ACL: Access Control Lists (Access Control list), which defines the permissions for users to operate or view specific things based on their user record attributes.

Fortunately, from Laravel 5.1.11 onwards, Laravel provides out-of-the-box authorization to meet the above requirements. We don't need to do any extra work, just use it.

Note: Before starting this section, refer to the upgrade guide to upgrade Laravel to Laravel 5.1.11. Otherwise, functions cannot be implemented.
2. What can I do?
The out-of-the-box ACL provided by Laravel is called Gate (this is not a Spark-like product name, but a name for the class and facade ).

The use of the Gate class (injection or use of the Gate facade) allows us to easily check whether a user (currently logged on user or specified user) allows specific operations. The check code is as follows:

If (Gate: denies ('UPDATE-post', $ post )){
Abort (403 );
}
Put this code in the controller. It will use the defined rule update-post to check whether the current authenticated user has the permission to update the specified article.

You can also use Gate: allows, which is opposite to the denies method. You can also use @ can in the Blade view template, and more, let's take a look at it.

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

3.1 define permissions

Let's define the user update article permission in AuthServiceProvider update-post as follows:

<? Php

Namespace App \ Providers;

Use Illuminate \ Contracts \ Auth \ Access \ Gate as your contract;
Use Illuminate \ Foundation \ Support \ Providers \ AuthServiceProvider as ServiceProvider;

Class AuthServiceProvider extends ServiceProvider {
/**
* Register all authentication/authorization services for the application.
     *
* @ Param \ Illuminate \ Contracts \ Auth \ Access \ Gate $ gate
* @ Return void
*/
Public function boot (Compute contract $ gate)
    {
Parent: registerPolicies ($ gate );

$ Gate-> define ('UPDATE-post', function ($ user, $ post ){
Return $ user-> id ===$ post-> user_id;
});
    }
}
As you can see, the first parameter for defining the permission closure is to specify the user. If the current user does not pass logon authentication, Gate will return false.

Of course, apart from the closure, you can also use the class method as the second parameter to replace the closure, 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 for permission check: check, allows, and denies. check and allows use the same functions, while denies and allows have the opposite functions.

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

If (Gate: denies ('UPDATE-post', $ post )){
Abort (403 );
}
If you define multiple parameters in the permission:

Gate: define ('delete-comment', function ($ user, $ post, $ comment ){
//
});
The check method is as follows:

If (Gate: allows ('delete-comment', [$ post, $ comment]) {
//
}
If you want to check whether a non-authenticated user has the permission to perform the operation, the call method is as follows:

If (Gate: forUser ($ user)-> allows ('UPDATE-post', $ post )){
//
}
3.3 Use Gate injection to check permissions

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

Public function somethingResolvedFromContainer (Gate $ gate)
{
If ($ gate-> denies ('UPDATE-post ')){
// Etc.
    }
}
3.4 use the User model to check permissions

Laravel's App \ User model now uses Authorizabletrait. Therefore, you can use the can and cannot methods provided by Laravel to correspond to the allows and denies methods of Gate respectively.

Therefore, we can also use the User model to check permissions:

Public function update (Request $ request, $ id)
{
$ Post = Post: findOrFail ($ id );

If ($ request-> user ()-> cannot ('UPDATE-post', $ post )){
Abort (403 );
    }

// Update the article...
}
3.5 Check permissions in Blade

You can use the @ can command in Blade to check permissions:

<A href = "/post/{$ post-> id}"> View articles </a>

@ Can ('UPDATE-post', $ post)
<A href = "/post/{$ post-> id}/edit"> edit an article </a>
@ Endcan
The opposite is the @ else command:

@ Can ('UPDATE-post', $ post)
<! -- The Current User Can Update The Post -->
@ Else
<! -- The Current User Can't Update The Post -->
@ Endcan
3.6 abort permission check

What if the administrator or super user has all permissions? Or what should you do if you want to temporarily switch the ACL logic for the user?

The before method provided by Gate allows you to return the result before executing other checks in some specific situations without checking the permissions:

$ Gate-> before (function ($ user, $ ability ){
If ($ user-> last_name === 'stauffer '){
Return true;
    }
});
Or when using the User:

$ Gate-> before (function ($ user, $ ability ){
If ($ user-> isOwner ()){
Return true;
    }
});
3.7 Strategy

As the application logic becomes more complex and more permissions need to be processed, defining all permissions in AuthServiceProvider is obviously not a wise practice. Therefore, Laravel introduces the strategy class, which is some native PHP class, similar to grouping a route by a controller based on resources, the policy class manages permissions by group based on resources.

Generate a policy class

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

Php artisan make: policy PostPolicy
The generated policy class is located in the app/Policies directory.

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

Protected $ policies = [
Post: class => PostPolicy: class,
];
Edit PostPolicy as follows:

<? Php

Namespace App \ Policies;

Use App \ User;
Use App \ Post;

Class PostPolicy {
/**
* Determine whether a given article can be updated by a given user
     *
* @ Param \ App \ User $ user
* @ Param \ App \ Post $ post
* @ Return bool
*/
Public function update (User $ user, Post $ post)
    {
Return $ user-> id ===$ post-> user_id;
    }
}
Note: All policy classes are parsed through service containers, which means that you can type any dependencies in the policy class constructor and they will be automatically injected.
Check policy

If a policy class is defined for a resource type, Gate uses the first parameter to determine which method to check for the policy class.

Therefore, to check whether you have the permission to update an article, you only need to pass in the article instance and update permission:

<? Php

Namespace App \ Http \ Controllers;

Use Gate;
Use App \ User;
Use App \ Post;
Use App \ Http \ Controllers \ Controller;

Class PostController extends Controller {
/**
* Update a given article
     *
* @ Param int $ id
* @ Return Response
*/
Public function update ($ id)
    {
$ Post = Post: findOrFail ($ id );

If (Gate: denies ('update', $ post )){
Abort (403 );
        }

// Update the article...
    }
}
You can also use the User model and Blade command to check permissions.

Laravel also provides a global help function policy to check permissions:

If (policy ($ post)-> update ($ user, $ post )){
//
}
3.8 controller authorization

Because most authorizations exit the Controller method when the permission check fails, there is a shortcut to check the permission in the Controller (provided by AuthorizesRequeststrait, which is used in the Controller of the base class Controller ):

<? Php

Namespace App \ Http \ Controllers;

Use App \ Post;
Use App \ Http \ Controllers \ Controller;

Class PostController extends Controller {
/**
* Update a given article
     *
* @ Param int $ id
* @ Return Response
*/
Public function update ($ id)
    {
$ Post = Post: findOrFail ($ id );
$ This-> authorize ('update', $ post );
// Update the article...
    }
}
As in the preceding example, if the authorization fails, a 403 error is thrown.

Finally, if your controller method name is the same as the method name in the policy class, for example, update, you can omit the first parameter of authorize:

Public function update ($ id ){
$ Post = Post: findOrFail ($ id );
$ This-> authorize ($ post );
// Update the article...
}
In addition, AuthorizesRequests also provides support for checking the permissions of non-authenticated users:

$ This-> authorizeForUser ($ user, 'update', $ post );

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.