Laravel 用户授权:判断是否授权 1 个改进

我们可以通过下面的几个方法来判断是否授权

使用策略授权动作

通过用户模型

Laravel 内置的 User 模型包含两个有用的方法来授权动作: can 和 cant。这个 can 方法需要指定授权的动作以及相关的模型。例如,判断是否授权一个用户更新指定的 Post 模型:

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

如果指定模型的 「策略已被注册」, can 方法会自动调用合适的策略并返回一个 boolean 值。如果没有策略注册到这个模型,can 方法会尝试调用和指定动作名称相匹配的基于闭包的 Gate。

不需要指定模型的动作

记住,一些动作,比如 create 并不需要指定模型实例。在这种情况下,可传递一个类名给 can 方法。这个类名将被用于判定使用哪种策略授权动作:

use App\Post;

if ($user->can('create', Post::class)) {
    // 执行相关策略中的 "create" 方法...
}

通过中间件

Laravel 包含一个可以在请求到达路由或者控制器之前就进行动作授权的中间件。默认情况下, Illuminate\Auth\Middleware\Authorize 中间件被指定到你的 App\Http\Kernel 类中的 can 键上。让我们用一个授权用户更新博客的例子来讲解一下 can 这个中间件的使用:

use App\Post;

Route::put('/post/{post}', function (Post $post) {
    // 当前用户可以进行更新操作...
})->middleware('can:update,post');

在这个例子中,我们传给了 can 中间件两个参数。第一个参数是需要授权的动作名称,第二个参数是我们希望传递给策略方法的路由参数。在这种情况下,我们使用了「 隐式路由绑定」,一个 Post 模型会被传递给策略方法。如果用户不被授权访问指定的动作,这个中间件将会生成带有 403 状态码的 HTTP 响应。

通过控制器辅助函数

除了在 User 模型中提供辅助方法以外,Laravel 也为继承  App\Http\Controllers\Controller 这个基类的控制器提供了一个有用的 authorize 方法。就像 can 方法一样,这个方法需要接收你想授权的动作和相关的模型作为参数。如果这个动作没有被授权, authorize 方法会抛出一个 Illuminate\Auth\Access\AuthorizationException 的异常,然后 Laravel 默认的异常处理器会将这个异常转化成带有  403 状态码的 HTTP 响应。

<?php

namespace App\Http\Controllers;

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

class PostController extends Controller
{
    /**
     * 更新指定博客帖子。
     *
     * @param  Request  $request
     * @param  Post  $post
     * @return Response
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function update(Request $request, Post $post)
    {
        $this->authorize('update', $post);

        // 当前用户可以更新博客...
    }
}

不需要指定模型的动作

和之前讨论的一样,一些动作,比如 create 并不需要指定模型实例的动作。在这种情况下,你可以传递一个类名给 authorize 方法。当授权这个动作时,这个类名将被用来判断使用哪个策略:

/**
 * 创建一个新的博客
 *
 * @param  Request  $request
 * @return Response
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function create(Request $request)
{
    $this->authorize('create', Post::class);

    // 当前用户可以新建博客...
}

授权资源控制器

如果你使用的是 资源控制器,那么你就可以在控制器构造方法里使用 authorizeResource 方法。该方法会把合适 can 中间件附加到资源控制器相应的方法中。

authorizeResource 方法接收模板类名作为第一个参数,包含模型 ID 的路由 / 请求参数的名称作为其第二个参数:

<?php

namespace App\Http\Controllers;

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

class PostController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Post::class, 'post');
    }
}

通过 Blade 模板

当编写 Blade 模板时,你可能希望页面的指定部分只展示给授权访问指定动作的用户。比如,你可能希望只展示更新的表单给有权更新博客的用户。在这样情况下,你可以使用 @can 和 @cannot 等一系列指令:

@can('update', $post)
    <!-- The Current User Can Update The Post -->
@elsecan('create', App\Post::class)
    <!-- The Current User Can Create New Post -->
@endcan

@cannot('update', $post)
    <!-- The Current User Can't Update The Post -->
@elsecannot('create', App\Post::class)
    <!-- The Current User Can't Create New Post -->
@endcannot

这些指令是编写 @if 和 @unless 语句的捷径。 @can 和 @cannot 语句分别转化为以下语句:

@if (Auth::user()->can('update', $post))
    <!-- The Current User Can Update The Post -->
@endif

@unless (Auth::user()->can('update', $post))
    <!-- The Current User Can't Update The Post -->
@endunless

不依赖模型的动作

与大多数其他授权方法一样,如果动作不需要模型实例,则可以将类名传递给 @ can 和 @ cannot 指令:

@can('create', App\Post::class)
    <!-- The Current User Can Create Posts -->
@endcan

@cannot('create', App\Post::class)
    <!-- The Current User Can't Create Posts -->
@endcannot
本文为 Wiki 文章,邀您参与纠错、纰漏和优化
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!