📜  laravel 中的门和策略 - PHP (1)

📅  最后修改于: 2023-12-03 15:02:36.036000             🧑  作者: Mango

Laravel 中的门和策略

在 Laravel 中,门和策略是一种很有用的控制访问权限的方法。门是定义访问权限的地方,策略是实现这些权限的地方。

门可以理解为在路由、控制器或任何方法中添加的中间件。它是定义访问授权的地方。

门有两种不同类型:授权门和检查门。授权门用于授权访问给定的资源或模型,检查门用于检查访问特定资源或模型的权限。

授权门

授权门用于授权或拒绝访问指定的资源或模型。在 Laravel 中,可以通过定义一个名为“policy”的类来创建授权门。这个类需要实现响应示例中所有的授权方法。以下是一个授权门的示例:

namespace App\Policies;

use App\Models\User;
use App\Models\Post;

class PostPolicy
{
    /**
     * Determine whether the user can view the post.
     *
     * @param  \App\Models\User  $user
     * @param  \App\Models\Post  $post
     * @return mixed
     */
    public function view(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }

    /**
     * Determine whether the user can create posts.
     *
     * @param  \App\Models\User  $user
     * @return mixed
     */
    public function create(User $user)
    {
        //
    }

    /**
     * Determine whether the user can update the post.
     *
     * @param  \App\Models\User  $user
     * @param  \App\Models\Post  $post
     * @return mixed
     */
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }

    /**
     * Determine whether the user can delete the post.
     *
     * @param  \App\Models\User  $user
     * @param  \App\Models\Post  $post
     * @return mixed
     */
    public function delete(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}

在这个示例中,我们定义了一个名为 PostPolicy 的类,并实现了在示例中使用的所有授权方法。

要启动门,需要在控制器构造函数中指定策略类:

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

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

    // Controller methods
}

在这个控制器的构造函数中,我们使用 策略方法authorizeResource() 并传递我们想要保护的授权类 Post 和请求中资源 ID 的名称 post。

接下来,我们可以在控制器方法中使用 身份验证 辅助函数,以确保用户有权限访问该方法:

public function show(Post $post)
{
    $this->authorize('view', $post);

    return view('posts.show', [
        'post' => $post,
    ]);
}

在这个示例中,我们使用 身份验证 方法 并传递 view 方法和资源 $post。 这将启动我们之前定义的 PostPolicy 类中的 view 方法,以确定用户是否有权限查看 $post。

检查门

检查门用于检查用户是否有访问资源或模型的权限。在 Laravel 中,您可以使用策略类来定义检查门。

以下是一个检查门的示例:

namespace App\Policies;

use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class UserPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can update the user.
     *
     * @param  \App\Models\User  $user
     * @param  \App\Models\User  $model
     * @return mixed
     */
    public function update(User $user, User $model)
    {
        return $user->id === $model->id;
    }
}

在这个示例中,我们为 User 模型创建了一个名为 UserPolicy 的策略类。我们实现了一个 update 方法,该方法检查用户是否有更新自己帐户的权限。

在控制器或其他方法中使用这个策略类之前,我们需要在进行中注册策略。 在 app\Providers\AuthServiceProvider.php 中可以注册它:

namespace App\Providers;

use App\Models\User;
use App\Policies\UserPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    protected $policies = [
        User::class => UserPolicy::class,
    ];

    public function boot()
    {
        $this->registerPolicies();

        //
    }
}

在这个授权服务提供程序中,我们将 UserPolicy 类与 User 模型关联的策略类注册到服务容器中。我们还需要将策略类传递给 Gate 类的策略类的静态 authorize 方法:

Gate::policy(User::class, UserPolicy::class);

现在,我们可以在需要验证用户权限的控制器或其他方法中使用 Gate 门面:

if (Gate::allows('update', $user)) {
    // The user can update the user...
}

if (Gate::denies('update', $user)) {
    // The user can't update the user...
}

在这个示例中,我们使用 allows 方法来确定用户是否可以更新另一个用户的帐户信息。使用 denies 方法可以实现相反的逻辑。

策略

策略是实现授权逻辑的地方。 Laravel 的策略是用于执行授权检查的简单类。这些类包含了定义的一些方法,使我们能够检查用户是否具有访问给定资源的权限。

以下是一个策略的示例:

namespace App\Policies;

use App\Models\User;
use App\Models\Post;

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

在这个示例中,我们实现了一个名为 update 的策略方法。这个方法接受一个 User 实例和一个 Post 实例,并判断是否可以更新该文章。在这个示例中,只有用户 ID 与文章的用户 ID 相同时才允许更新文章。

要使用策略,需要在使用策略的控制器内启用建筑物策略行为:

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

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

    // ...
}

在该示例中,我们可以看到 authorizeResource 方法将两个参数传递:一个模型类(在这种情况下,Post::class)和请求中资源参数(在此示例中为$routeKeyName)。

策略内部的资源方法将自动查找并调用,以执行相应处理逻辑。为了利用此功能,您必须遵循给定的命名约定。所需的策略方法及其相应的 HTTP 谓词如下:

  • view:查看给定模型("查看")。
  • create:创建给定模型("创建")。
  • update:更新给定模型("更新")。
  • delete:删除给定模型("删除")。
  • restore:恢复给定模型("还原")。
  • forceDelete:永久性地从数据库中删除给定的模型("强制删除")。

需要注意的是,可以添加与您的应用程序相关的自定义方法签名。

当您不使用 {{!! $model->renderModelTable() !!}} Blade 模板渲染器时,可以通过通过手动注册资源授权来在控制器中使用策略。

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;

class PostController extends Controller
{
    /**
     * Show the form for creating a new post.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        if (Gate::allows('create', Post::class)) {
        // Do something with create permission...
        }

        return view('posts.create');
    }

    // ...
}

在 this 示例中,我们使用 allows 方法来确定当前用户是否具有创建 Post 实例的权限。如果这是情况,就做一些事情。否则,我们显示一个视图。

总结

通过使用门和策略,在 Laravel 中可以更轻松地实现授权逻辑,并实现对资源的访问控制。 Laravel 的策略非常灵活,使我们能够实现许多各种各样的授权逻辑。