Authorized
Brief introduction
In addition to providing out-of-the-box licensing services, Laravel provides many simple ways to manage authorization logic and resource access control. These various methods and help functions make it easier for you to manage your authorization logic. We will interpret it in this chapter one by one.
Defining capabilities
The simplest way to determine whether a user has the ability to perform a given action is to use the Illuminate\auth\access\gate class to define the corresponding capability. The Authserviceprovider class provided by Laravel is the recommended location for defining these capabilities. Let's look at an example where we define a update-post capability that receives a current User and a post model. In this capability, we need to determine whether the user ID matches the user_id of the post:
Registerpolicies ($gate); $gate->define (' Update-post ', function ($user, $post) { return $user->id = = = $post->user_id; });} }
Note that in the example above we did not check whether the given $user is null. This is because when a given user is not authenticated or the user is not specified by the Foruser method, the Gate class automatically returns false for all abilities.
Class-based capabilities
In addition to using Closures as a callback for authorization checking, you can also register the ability by passing methods in the class, and when needed, the classes are parsed by the service container:
$gate->define (' update-post ', ' Class@method ');
Authorization check Blocker
Sometimes, you may need to grant all the capabilities of a pass to certain special users, and at this point you can use the Before method to define a callback that will run before all authorization checks:
$gate->before (function ($user, $ability) { if ($user->issuperadmin ()) { return true; }});
If the before callback function returns a non-empty result, the result will be the result of the check.
You can also use the After method to define a callback function that executes after each capability authorization check, but you cannot modify the result of the check within this callback function:
$gate->after (function ($user, $ability, $result, $arguments) { //});
Inspection capabilities
Through Gate masks
Once a competency is defined, we can examine the capabilities in a variety of ways. First, we can use the check,allows of the Gate mask, or the denies method. All of these methods receive the name of the capability, and the additional parameters are passed to the corresponding ability's callback function. You do not need to pass the current user into these methods, the Gate will automatically pre-position the current user into the parameters and pass the callback function to the ability. So when we examine the previously defined update-post capabilities, we only need to pass the instance of the post to the denies method:
Of course, the allows method, in contrast to denies, returns true if the action is authorized. The check method is the alias of the allows method.
Ability to check for a specified user
If you want to use Gate mask to check whether other users who are not currently authorized through the user have the appropriate capabilities, you can use the Foruser method:
if (Gate::foruser ($user)->allows (' Update-post ', $post)) { //}
Passing Multiple parameters
Of course, the ability's callback function can receive multiple parameters:
Gate:define (' Delete-comment ', function ($user, $post, $comment) { //});
If you have the ability to receive multiple parameters, you can simply pass the Gate mask method to the array consisting of multiple parameters:
if (gate::allows (' delete-comment ', [$post, $comment])) { //}
Ability to check with user model
In fact, you can check the user's capabilities through an instance of the users model. The default Laravel App\user model uses the authorizable trait, which contains two methods: can and cannot. The two methods are the same as the allows of the Gate mask and the denies method. We also use the examples above that have been used, modified as follows:
User ()->cannot (' Update-post ', $post)) { abort (403); } Update Post ... }}
Of course, the can method is the opposite of cannot:
if ($request->user ()->can (' Update-post ', $post)) { //update post ...}
Checking capabilities in the Blade template
For convenience, Laravel provides a @can Blade directive to quickly check whether the currently authorized user has the specified capability. Like what:
ID}} ">view Post@can (' Update-post ', $post) ID}}/edit" >edit post@endcan
You can also use @else instructions to match @can instructions:
@can (' Update-post ', $post)
@else
@endcan
Ability to check in form requests
You can also verify the capabilities defined in the Gate mask by using the custom Authoriza method in the form request (inherited from request, which is used for form validation):
/** * Determine if the user is authorized to make this request. * * @return BOOL */Public Function authorize () { $postId = $this->route (' post '); Return cate::allows (' Update ', Post::findorfail ($postId)); }
Strategy (policies)
Create a policy
In order not to let you put all the authorization logic into the Authserviceprovider so that the application grows into a large and cumbersome application. Laravel allows you to separate your authorization logic through the Policy class. The policy class is actually a native PHP class that contains authorization logic groups.
First, let's generate a policy to manage the authorization of our Post. You can use the Make:policy command to generate a policy. The resultant policy is stored in the App/policies directory:
PHP Artisan Make:policy Postpolicy
Enrollment Policy
Once the policy exists, we also need to register in the Gate class. A policies property is included in Authserviceprovider that holds the mappings between all entities and the policy. Therefore, we need to assign the policy of the Post model to the Postpolice class:
Postpolicy::class, ]; /** * Register any application authentication/authorization services. * * @param \illuminate\contracts\auth\access\gate $gate * @return void * /Public Function boot ( Gatecontract $gate) { $this->registerpolicies ($gate); }}
Writing policies
Once the policy has been generated and registered, we can add a validation method for the authorization of all capabilities. For example, let's define an update method in the Postpolicy class to verify that the given user has the ability to update Post:
id = = = $post->user_id; }}
You can continue to add additional methods in the policy that require authorization validation. For example, you can continue to define show,destroy for various actions that verify Post, or AddComment methods.
Note: All policy classes are resolved through the service container. This means that you can use type hints to rely on dependency injection in the constructor of the policy class.
Intercept all Inspections
Sometimes, you may need to give a pass to the specified user with all the capabilities, and you can define the before method in the policy class. This method runs before all other methods in the policy are executed:
Public function before ($user, $ability) { if ($user->issuperadmin ()) { return true; }}
If the Before method returns a non-null value, the result will be used as the basis for determining the result of authorization validation.
Check Policy
The method of the policy class and the method based on the authorization callback are called as Closure in the same way. You can use Gate masks, User models, @can Blade instructions or policy helper to perform authorization checks.
Through Gate masks
Gate determines which policy should be used by checking the type of arguments passed to the method. So, if we pass the Post instance to the denies method, the Gate will automatically use the corresponding Postpolicy for authorization verification:
Through the user's model
The Can and cannot methods in the User model will also automatically match the corresponding policy when the given parameters are available. These methods provide a convenient way to verify that any user instance has the capabilities given:
if ($user->can (' Update ', $post)) { //}if ($user->cannot (' Update ', $post)) { //}
Through the Blade template
As we would expect, @can the Blade directive automatically matches the corresponding policy when the given parameter is available:
@can (' Update ', $post)
@endcan
Through policy Helper
The global Help method policy can parse the appropriate policy class by the given class. For example, we can pass a Post instance to the policy helper method, which returns the corresponding Postpolicy class:
if (Policy ($post)->update ($user, $post)) { //}
Controller authorization
By default, Ap\http\controllers\controller-based classes in Laravel introduce authorizesrequests trait (traits). This trait provides a authorize method to quickly verify that the given action has the ability to execute, and throws a httpexception if it does not have the corresponding ability.
The authorize method shares other ways of authorizing visas, such as Gate::allows and $user->can (). So, let's use the authorize method to quickly identify if a request has the ability to update Post:
Authorize (' Update ', $post); Update Post ... }}
If this action passes the authorization, the controller will continue to execute the following logic. Otherwise, an HttpException error is automatically thrown, which generates an Http response of 403 not Authorized. As you can see, the authorize method is a convenient way to do this by using only one statement to perform authorization validation or throwing exceptions.
Authorizerequests trait also provides the Authorizeforuser method to authenticate users of non-current users with a given capability:
$this->authorizeforuser ($user, ' Update ', $post);
Automatic determination of policy methods
Typically, the methods in the policy class correspond to the method in the controller. For example, in the Update method above, the method of the Controller and the method of the policy used the same name: update.
For this reason, Laravel allows you to simply pass an instance parameter to the authorize method, in which the laravel determines the invocation of the policy method automatically based on the naming of the current method. In the above example, because the authorize method is called in the Update method in the controller, the update in Postpolicy will be called:
/** * Update the given post. * * @param int $id * @return Response */Public Function Update ($id) { $post = Post::findorfail ($id); $this->authorize ($post); Update Post ...}