Laravel Laravel
  • Prologue

    • Release Notes
    • Upgrade Guide
    • Contribution Guide
    • API Documentation
  • Setup

    • Installation
    • Configuration
    • Homestead
    • Valet
  • Tutorials

    • Basic Task List
    • Intermediate Task List
  • The Basics

    • Routing
    • Middleware
    • Controllers
    • Requests
    • Responses
    • Views
    • Blade Templates
  • Architecture Foundations

    • Request Lifecycle
    • Application Structure
    • Service Providers
    • Service Container
    • Contracts
    • Facades
  • Services

    • Authentication
    • Authorization
    • Artisan Console
    • Billing
    • Cache
    • Collections
    • Elixir
    • Encryption
    • Errors & Logging
    • Events
    • Filesystem / Cloud Storage
    • Hashing
    • Helpers
    • Localization
    • Mail
    • Package Development
    • Pagination
    • Queues
    • Redis
    • Session
    • SSH Tasks
    • Task Scheduling
    • Testing
    • Validation
  • Database

    • Getting Started
    • Query Builder
    • Migrations
    • Seeding
  • Eloquent ORM

    • Getting Started
    • Relationships
    • Collections
    • Mutators
    • Serialization
Icon

WARNING You're browsing the documentation for an old version of Laravel. Consider upgrading your project to Laravel 11.x.

Authorization

  • Introduction
  • Defining Abilities
  • Checking Abilities
    • Via The Gate Facade
    • Via The User Model
    • Within Blade Templates
    • Within Form Requests
  • Policies
    • Creating Policies
    • Writing Policies
    • Checking Policies
  • Controller Authorization

Introduction

In addition to providing authentication services out of the box, Laravel also provides a simple way to organize authorization logic and control access to resources. There are a variety of methods and helpers to assist you in organizing your authorization logic, and we'll cover each of them in this document.

Defining Abilities

The simplest way to determine if a user may perform a given action is to define an "ability" using the Illuminate\Auth\Access\Gate class. The AuthServiceProvider which ships with Laravel serves as a convenient location to define all of the abilities for your application. For example, let's define an update-post ability which receives the current User and a Post model. Within our ability, we will determine if the user's id matches the post's user_id:

<?php

namespace App\Providers;

use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * Register any application authentication / authorization services.
     *
     * @param  \Illuminate\Contracts\Auth\Access\Gate  $gate
     * @return void
     */
    public function boot(GateContract $gate)
    {
        $this->registerPolicies($gate);

        $gate->define('update-post', function ($user, $post) {
            return $user->id == $post->user_id;
        });
    }
}

Note that we did not check if the given $user is not NULL. The Gate will automatically return false for all abilities when there is not an authenticated user or a specific user has not been specified using the forUser method.

Class Based Abilities

In addition to registering Closures as authorization callbacks, you may register class methods by passing a string containing the class name and the method. When needed, the class will be resolved via the service container:

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

Intercepting Authorization Checks

Sometimes, you may wish to grant all abilities to a specific user. For this situation, use the before method to define a callback that is run before all other authorization checks:

$gate->before(function ($user, $ability) {
    if ($user->isSuperAdmin()) {
        return true;
    }
});

If the before callback returns a non-null result that result will be considered the result of the check.

You may use the after method to define a callback to be executed after every authorization check. However, you may not modify the result of the authorization check from an after callback:

$gate->after(function ($user, $ability, $result, $arguments) {
    //
});

Checking Abilities

Via The Gate Facade

Once an ability has been defined, we may "check" it in a variety of ways. First, we may use the check, allows, or denies methods on the Gate facade. All of these methods receive the name of the ability and the arguments that should be passed to the ability's callback. You do not need to pass the current user to these methods, since the Gate will automatically prepend the current user to the arguments passed to the callback. So, when checking the update-post ability we defined earlier, we only need to pass a Post instance to the denies method:

<?php

namespace App\Http\Controllers;

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

class PostController extends Controller
{
    /**
     * Update the given post.
     *
     * @param  int  $id
     * @return Response
     */
    public function update($id)
    {
        $post = Post::findOrFail($id);

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

        // Update Post...
    }
}

Of course, the allows method is simply the inverse of the denies method, and returns true if the action is authorized. The check method is an alias of the allows method.

Checking Abilities For Specific Users

If you would like to use the Gate facade to check if a user other than the currently authenticated user has a given ability, you may use the forUser method:

if (Gate::forUser($user)->allows('update-post', $post)) {
    //
}

Passing Multiple Arguments

Of course, ability callbacks may receive multiple arguments:

Gate::define('delete-comment', function ($user, $post, $comment) {
    //
});

If your ability needs multiple arguments, simply pass an array of arguments to the Gate methods:

if (Gate::allows('delete-comment', [$post, $comment])) {
    //
}

Via The User Model

Alternatively, you may check abilities via the User model instance. By default, Laravel's App\User model uses an Authorizable trait which provides two methods: can and cannot. These methods may be used similarly to the allows and denies methods present on the Gate facade. So, using our previous example, we may modify our code like so:

<?php

namespace App\Http\Controllers;

use App\Post;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    /**
     * Update the given post.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        $post = Post::findOrFail($id);

        if ($request->user()->cannot('update-post', $post)) {
            abort(403);
        }

        // Update Post...
    }
}

Of course, the can method is simply the inverse of the cannot method:

if ($request->user()->can('update-post', $post)) {
    // Update Post...
}

Within Blade Templates

For convenience, Laravel provides the @can Blade directive to quickly check if the currently authenticated user has a given ability. For example:

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

@can('update-post', $post)
    <a href="/post/{{ $post->id }}/edit">Edit Post</a>
@endcan

You may also combine the @can directive with @else directive:

@can('update-post', $post)
    <!-- The Current User Can Update The Post -->
@else
    <!-- The Current User Can't Update The Post -->
@endcan

Within Form Requests

You may also choose to utilize your Gate defined abilities from a form request's authorize method. For example:

/**
 * Determine if the user is authorized to make this request.
 *
 * @return bool
 */
public function authorize()
{
    $postId = $this->route('post');

    return Gate::allows('update', Post::findOrFail($postId));
}

Policies

Creating Policies

Since defining all of your authorization logic in the AuthServiceProvider could become cumbersome in large applications, Laravel allows you to split your authorization logic into "Policy" classes. Policies are plain PHP classes that group authorization logic based on the resource they authorize.

First, let's generate a policy to manage authorization for our Post model. You may generate a policy using the make:policy artisan command. The generated policy will be placed in the app/Policies directory:

php artisan make:policy PostPolicy

Registering Policies

Once the policy exists, we need to register it with the Gate class. The AuthServiceProvider contains a policies property which maps various entities to the policies that manage them. So, we will specify that the Post model's policy is the PostPolicy class:

<?php

namespace App\Providers;

use App\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        Post::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 methods for each ability it authorizes. For example, let's define an update method on our PostPolicy, which will determine if the given User can "update" a Post:

<?php

namespace App\Policies;

use App\User;
use App\Post;

class PostPolicy
{
    /**
     * Determine if the given post can be updated by the user.
     *
     * @param  \App\User  $user
     * @param  \App\Post  $post
     * @return bool
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

You may continue to define additional methods on the policy as needed for the various abilities it authorizes. For example, you might define show, destroy, or addComment methods to authorize various Post actions.

Note: All policies are resolved via the Laravel service container, meaning you may type-hint any needed dependencies in the policy's constructor and they will be automatically injected.

Intercepting All Checks

Sometimes, you may wish to grant all abilities to a specific user on a policy. For this situation, define a before method on the policy. This method will be run before all other authorization checks on the policy:

public function before($user, $ability)
{
    if ($user->isSuperAdmin()) {
        return true;
    }
}

If the before method returns a non-null result that result will be considered the result of the check.

Checking Policies

Policy methods are called in exactly the same way as Closure based authorization callbacks. You may use the Gate facade, the User model, the @can Blade directive, or the policy helper.

Via The Gate Facade

The Gate will automatically determine which policy to use by examining the class of the arguments passed to its methods. So, if we pass a Post instance to the denies method, the Gate will utilize the corresponding PostPolicy to authorize actions:

<?php

namespace App\Http\Controllers;

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

class PostController extends Controller
{
    /**
     * Update the given post.
     *
     * @param  int  $id
     * @return Response
     */
    public function update($id)
    {
        $post = Post::findOrFail($id);

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

        // Update Post...
    }
}

Via The User Model

The User model's can and cannot methods will also automatically utilize policies when they are available for the given arguments. These methods provide a convenient way to authorize actions for any User instance retrieved by your application:

if ($user->can('update', $post)) {
    //
}

if ($user->cannot('update', $post)) {
    //
}

Within Blade Templates

Likewise, the @can Blade directive will utilize policies when they are available for the given arguments:

@can('update', $post)
    <!-- The Current User Can Update The Post -->
@endcan

Via The Policy Helper

The global policy helper function may be used to retrieve the Policy class for a given class instance. For example, we may pass a Post instance to the policy helper to get an instance of our corresponding PostPolicy class:

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

Controller Authorization

By default, the base App\Http\Controllers\Controller class included with Laravel uses the AuthorizesRequests trait. This trait provides the authorize method, which may be used to quickly authorize a given action and throw a AuthorizationException if the action is not authorized.

The authorize method shares the same signature as the various other authorization methods such as Gate::allows and $user->can(). So, let's use the authorize method to quickly authorize a request to update a Post:

<?php

namespace App\Http\Controllers;

use App\Post;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    /**
     * Update the given post.
     *
     * @param  int  $id
     * @return Response
     */
    public function update($id)
    {
        $post = Post::findOrFail($id);

        $this->authorize('update', $post);

        // Update Post...
    }
}

If the action is authorized, the controller will continue executing normally; however, if the authorize method determines that the action is not authorized, a AuthorizationException will automatically be thrown which generates a HTTP response with a 403 Not Authorized status code. As you can see, the authorize method is a convenient, fast way to authorize an action or throw an exception with a single line of code.

The AuthorizesRequests trait also provides the authorizeForUser method to authorize an action on a user that is not the currently authenticated user:

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

Automatically Determining Policy Methods

Frequently, a policy's methods will correspond to the methods on a controller. For example, in the update method above, the controller method and the policy method share the same name: update.

For this reason, Laravel allows you to simply pass the instance arguments to the authorize method, and the ability being authorized will automatically be determined based on the name of the calling function. In this example, since authorize is called from the controller's update method, the update method will also be called on the PostPolicy:

/**
 * Update the given post.
 *
 * @param  int  $id
 * @return Response
 */
public function update($id)
{
    $post = Post::findOrFail($id);

    $this->authorize($post);

    // Update Post...
}
last update:2018-06-05 12:39

成为Laravel合作伙伴

Laravel Partners是提供一流Laravel开发和咨询服务的精英商店。我们每个合作伙伴都可以帮助您制定一个精美,结构完善的项目.

我们的伙伴
Laravel
亮点
  • Our Team
  • 发布说明
  • 入门
  • 路由
  • Blade 模板
  • 身份验证
  • 用户授权
  • Artisan 控制台
  • 数据库
  • Eloquent ORM
  • 测试
资源
  • Laravel Bootcamp
  • Laracasts
  • Laravel News
  • Laracon
  • Laracon EU
  • Laracon India
  • Jobs
  • Forums
  • Trademark
  • 版本发布时间
  • 包开发
  • 命令行应用
  • TALL stack全栈开发
  • Blade UI Kit
  • 前端资源构建
伙伴
  • WebReinvent
  • Vehikl
  • Tighten
  • 64 Robots
  • Active Logic
  • Byte 5
  • Curotec
  • Cyber-Duck
  • DevSquad
  • Jump24
  • Kirschbaum
生态系统
  • Cashier
  • Dusk
  • Echo
  • Envoyer
  • Forge
  • Horizon
  • Nova
  • Octane
  • Sail
  • Sanctum
  • Scout
  • Spark
  • Telescope
  • Valet
  • Vapor

Laravel是一个具有表达力,优雅语法的Web应用程序框架。我们认为,发展必须是一种令人愉悦的创造力,才能真正实现。Laravel试图通过减轻大多数Web项目中使用的常见任务来减轻开发的痛苦.

Laravel是Taylor Otwell的商标.
Copyright © 2011-2025 Laravel中文网 LLC.

  • Twitter
  • GitHub
  • Discord
Laravel 全栈开发网 推荐使用阿里云 按Ctrl+D试试