Laravel: 路由中间件和策略的区别

Laravel: Difference Between Route Middleware and Policy

使用 laravel 开发应用程序 我意识到可以使用 Policy 完成的工作完全可以使用 Middleware 完成。假设如果 he/she 不是信息的所有者,我想阻止用户更新路由,我可以轻松地从路由中进行检查,并且可以从策略中执行相同的操作。

所以我的问题是为什么我应该使用 policy 而不是中间件,反之亦然

路由中间件允许您将请求处理应用于大范围的路由,而不是在每个控制器操作中重复代码 - 检查身份验证和重定向访客就是一个很好的例子。相反,控制器包含特定 routes/actions 独有的逻辑 - 您可以为此使用中间件,但每个路由的逻辑都需要单独的中间件,这一切都会变得非常混乱。

Policies/abilities 只是一种检查用户权限的方法——您可以从控制器、中间件或其他任何地方查询它们。它们只有 return true 或 false,因此它们不等同于控制器或中间件。大多数时候,能力会将用户与另一个模型进行比较,该模型将根据发送到控制器操作的标识符进行加载,但也可能有一些应用程序与中间件一起使用。

我目前正在对我的角色、权限和路由进行小型重构,并问自己同样的问题。

从表面上看,真正的中间件和策略似乎执行相同的总体思想。检查用户是否可以做他们正在做的事情。

参考这里的 laravel 文档...

中间件 "May I see this? May I go here?"

HTTP middleware provide a convenient mechanism for filtering HTTP requests entering your application. For example, Laravel includes a middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware will redirect the user to the login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.

Of course, additional middleware can be written to perform a variety of tasks besides authentication. A CORS middleware might be responsible for adding the proper headers to all responses leaving your application. A logging middleware might log all incoming requests to your application.

https://laravel.com/docs/master/middleware#introduction

在我的阅读中,中间件是关于在请求级别运行的。以"Can this user see a page?"或"Can this user do something here?"

而言

如果是这样,它将转到与该页面关联的控制器方法。有趣的是,中间件可能会说,"Yes you may go there, but I'll write down that you are going." 等等

完成后。它对用户正在做什么没有更多的控制权或发言权。我将其视为中间人的另一种方式。

政策 "Can I do this? Can I change this?"

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.

https://laravel.com/docs/master/authorization#introduction

然而,政策似乎更关心。用户可以更新任何条目,还是只能更新他们的条目?

这些问题似乎适合控制器方法,其中组织了对资源的所有操作调用。检索此对象、存储或更新文章。

一样,中间件会使路由变得非常混乱且难以管理。这是我的路线文件中的示例:

问题

    Route::group(['middleware' =>'role:person_type,person_type2',], function () {
        Route::get('download-thing/{thing}', [
             'as' => 'download-thing', 
             'uses' => 'ThingController@download'
        ]);
    }); 

这在我的路线文件中很难阅读!

另一种策略

//ThingController
public function download(Thing $thing)
{
    //Policy method and controller method match, no need to name it
    $this->authorize($thing);

    //download logic here....
}

我也问过自己同样的问题。在实践中,我主要使用中间件。 我最常见的用法是只允许特定用户授权,例如:

public function update(User $user, user $model)
{
    return $user->id === $model->id;
}

不过,即使在上面的例子中,是的,没有它也可以,在控制器中编写自己的逻辑来做同样的事情。

我也喜欢before的方法,我用它来让管理员full-privileges换一个模型,例如:

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

不过,我开始在某些 Laravel 项目上使用策略的主要原因是因为您可以使用 blade 做些什么。如果您发现自己在 blade 文件中多次为同一用户授权设置权限,例如,显示编辑按钮,那么策略可能会变得非常有用,因为您可以对它们执行以下操作(以及更多操作):

@can('update', $post)
<button class="btn btn-primary">Edit Post</button>
@endcan

@cannot('create', App\Models\Post::class)
<div class="alert alert-warning">You are not allowed to create a post</div>
@endcannot

我有时发现这些 Policy-referencing blade 方法非常有用,当我想在一个地方分组授权时。