今天,我们将讨论Laravel Web框架的授权系统。 Laravel框架以门和策略的形式实现授权。 在介绍了门和策略之后,我将通过实现一个自定义示例来演示概念。
我认为您已经了解了内置的Laravel身份验证系统,因为这对于理解授权概念至关重要。 显然,授权系统与身份验证系统协同工作,以标识合法的用户会话。
如果您不了解Laravel身份验证系统,我强烈建议您阅读官方文档 ,它为您提供了有关该主题的动手知识。
Laravel的授权方式
到目前为止,您应该已经知道Laravel授权系统具有两种形式-门和策略。 尽管这听起来可能很复杂,但是我想说,一旦掌握了它,就很容易实现它!
Gates使您可以使用基于封闭的简单方法来定义授权规则。 换句话说,当您想要授权与任何特定模型都不相关的动作时,门是实现该逻辑的理想场所。
让我们快速看一下基于门的授权的外观:
...
...
Gate::define('update-post', function ($user, $post) {
return $user->id == $post->user_id;
});
...
...
上面的代码段定义了可以在应用程序中的任何位置调用的授权规则update-post
。
另一方面,要对任何模型的授权逻辑进行分组时,应使用策略。 例如,假设您的应用程序中有一个Post模型,并且您想授权该模型的CRUD操作。 在这种情况下,这就是您需要实施的策略。
class PostPolicy
{
public function view(User $user, Post $post) {}
public function create(User $user) {}
public function update(User $user, Post $post) {}
public function delete(User $user, Post $post) {}
}
如您所见,这是一个非常简单的策略类,它定义了Post
模型的CRUD操作的授权。
因此,这是Laravel中的闸门和政策的简介。 从下一部分开始,我们将对每个元素进行实际演示。
盖茨
在本节中,我们将看到一个真实的例子来理解门的概念。
通常,当您需要注册组件或服务时,最终还是要看Laravel服务提供商。 遵循该约定,让我们继续在app/Providers/AuthServiceProvider.php
定义我们的自定义门,如以下代码片段所示。
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('update-post', function ($user, $post) {
return $user->id == $post->user_id;
});
}
}
在boot
方法中,我们定义了自定义门:
Gate::define('update-post', function ($user, $post) {
return $user->id == $post->user_id;
});
在定义门时,它会根据闭门定义中定义的授权逻辑,采用闭包返回TRUE或FALSE的方式。 除了闭包功能外,还有其他定义门的方法。
例如,以下门定义调用控制器动作而不是闭合函数。
Gate::define('update-post', 'ControllerName@MethodName');
现在,让我们继续并添加自定义路由,以便我们可以演示基于门的授权如何工作。 在路由文件routes/web.php
,添加以下路由。
Route::get('service/post/gate', 'PostController@gate');
我们也创建一个关联的控制器文件app/Http/Controllers/PostController.php
。
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Support\Facades\Gate;
class PostController extends Controller
{
/* Make sure you don't user Gate and Policy altogether for the same Model/Resource */
public function gate()
{
$post = Post::find(1);
if (Gate::allows('update-post', $post)) {
echo 'Allowed';
} else {
echo 'Not Allowed';
}
exit;
}
}
在大多数情况下,你会最终使用要么allows
或denies
的方法Gate
门面授权某个动作。 在上面的示例中,我们使用了allows
方法来检查当前用户是否能够执行update-post
操作。
眼睛敏锐的用户会注意到,我们仅将第二个参数$post
传递给了闭包。 第一个参数是当前登录的用户,由Gate
门面自动注入。
因此,这就是您应该使用Gates授权Laravel应用程序中的操作的方式。 下一部分将讨论如何使用策略,如果您希望对模型实施授权。
政策规定
正如我们前面所讨论的,当您想要对任何特定模型或资源进行逻辑上的授权操作分组时,这就是您要寻找的策略。
在本节中,我们将为Post模型创建一个策略,该策略将用于授权所有CRUD操作。 我假设您已经在应用程序中实现了Post模型; 否则,类似的事情将会发生。
在创建存根代码时,Laravel artisan
命令是您最好的朋友。 您可以使用以下artisan命令为Post模型创建策略。
$php artisan make:policy PostPolicy --model=Post
如您所见,我们提供了--model=Post
参数,以便它创建所有CRUD方法。 如果没有,它将创建一个空白的Policy类。 您可以在app/Policies/PostPolicy.php
找到新创建的Policy类。
让我们用以下代码替换它。
<?php
namespace App\Policies;
use App\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view the post.
*
* @param \App\User $user
* @param \App\Post $post
* @return mixed
*/
public function view(User $user, Post $post)
{
return TRUE;
}
/**
* Determine whether the user can create posts.
*
* @param \App\User $user
* @return mixed
*/
public function create(User $user)
{
return $user->id > 0;
}
/**
* Determine whether the user can update the post.
*
* @param \App\User $user
* @param \App\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\User $user
* @param \App\Post $post
* @return mixed
*/
public function delete(User $user, Post $post)
{
return $user->id == $post->user_id;
}
}
为了能够使用我们的Policy类,我们需要使用Laravel服务提供商注册它,如以下代码片段所示。
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use App\Post;
use App\Policies\PostPolicy;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Post::class => PostPolicy::class
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
}
}
我们已经在$policies
属性中添加了Policy的映射。 它告诉Laravel调用相应的策略方法来授权CRUD操作。
您还需要使用registerPolicies
方法注册策略,就像在boot
方法中所做的那样。
进一步讲,让我们在routes/web.php
文件中创建几个自定义路由,以便我们可以在那里测试Policy方法。
Route::get('service/post/view', 'PostController@view');
Route::get('service/post/create', 'PostController@create');
Route::get('service/post/update', 'PostController@update');
Route::get('service/post/delete', 'PostController@delete');
最后,让我们在app/Http/Controllers/PostController.php
创建一个关联的控制器。
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Support\Facades\Auth;
class PostController extends Controller
{
public function view()
{
// get current logged in user
$user = Auth::user();
// load post
$post = Post::find(1);
if ($user->can('view', $post)) {
echo "Current logged in user is allowed to update the Post: {$post->id}";
} else {
echo 'Not Authorized.';
}
}
public function create()
{
// get current logged in user
$user = Auth::user();
if ($user->can('create', Post::class)) {
echo 'Current logged in user is allowed to create new posts.';
} else {
echo 'Not Authorized';
}
exit;
}
public function update()
{
// get current logged in user
$user = Auth::user();
// load post
$post = Post::find(1);
if ($user->can('update', $post)) {
echo "Current logged in user is allowed to update the Post: {$post->id}";
} else {
echo 'Not Authorized.';
}
}
public function delete()
{
// get current logged in user
$user = Auth::user();
// load post
$post = Post::find(1);
if ($user->can('delete', $post)) {
echo "Current logged in user is allowed to delete the Post: {$post->id}";
} else {
echo 'Not Authorized.';
}
}
}
您可以使用多种方法来使用策略授权操作。 在上面的示例中,我们使用了User
模型来授权Post
模型操作。
用户模型提供授权目的订立两个有用的方法can
和cant
。 can
方法用于检查当前用户是否能够执行特定操作。 和的对应物can
的方法,所述cant
的方法,被用于确定该动作执行的无力。
让我们从控制器中获取view
方法的代码片段,以view
其确切功能。
public function view()
{
// get current logged in user
$user = Auth::user();
// load post
$post = Post::find(1);
if ($user->can('view', $post)) {
echo "Current logged in user is allowed to update the Post: {$post->id}";
} else {
echo 'Not Authorized.';
}
}
首先,我们加载当前登录的用户,这为我们提供了User模型的对象。 接下来,我们使用Post模型加载示例帖子。
向前,我们已经使用了User模型的can
方法来授权Post
模型的view
动作。 can
方法的第一个参数是您要授权的操作名称,第二个参数是您要针对其授权的模型对象。
这说明了如何使用User
模型通过策略授权操作。 另外,如果您在授权某个操作的同时处于控制器中,则也可以使用Controller Helper 。
…
$this->authorize('view', $post);
…
如您所见,如果使用Controller Helper,则不需要加载User模型。
这就是您可以使用的策略的概念,并且在授权模型或资源时非常方便,因为它允许您将授权逻辑集中在一个位置。
只要确保您对模型的相同操作完全不使用门和策略,否则会造成问题。 今天就从我这边开始,我将其称为一天!
结论
今天,正是Laravel授权在我的文章中占据了中心位置。 在本文的开头,我介绍了Laravel授权的主要元素,闸门和策略。
之后,我们经历了创建自定义门和策略的过程,以了解其在现实世界中的工作方式。 我希望您喜欢这篇文章,并从Laravel的背景中学到了一些有用的东西。
对于那些刚刚开始使用Laravel或希望通过扩展来扩展您的知识,网站或应用程序的人,我们可以在Envato Market上进行各种研究。
与往常一样,我很乐意使用以下供稿以评论的形式收到您的来信!
翻译自: https://code.tutsplus.com/tutorials/gates-and-policies-in-laravel--cms-29780