I. Giới thiệu:
1. Vấn đề:
- Trong thực tế khi triển khai những dự án thì bạn sẽ gặp những khó khăn trong vấn đề trong cấp các quyền truy cập cho từng Model ở những màn hình đặc thù nhằm để bảo mật thông tin thì đây có thể là bài viết bạn đang cần có thể giúp bạn dễ dàng hơn trong quá trình xây dựng dự án của mình.
- Có 2 cách đơn giản để bạn phân quyền cho hệ thống của mình được Laravel hỗ trợ sẳn là Gate và Policy. Cả 2 cách này đều được sử dụng rộng rải và thông thường thì sẻ sử dụng Gate khi mà bạn phân quyền những thứ không liên quan đến bất kì model hay resource nào cả ví dụ xem một trang admininistrator dashboard. Ngược lại, thì đối với Policy thì sử dụng bạn phân quyền liên quan đến model hoặc resource.
- Trong phần này, mình sẽ giới thiệu cho các bạn 1 công cụ rất hữu cho việc xác thực người dùng rất mạnh của Laravel hỗ trợ đó là Policy.
II. Làm việc với Policy:
1. Khởi tạo Policy:
- Đầu tiên các bạn generate ra file policy tương ứng, Laravel có hỗ trợ cú pháp make:policy để giúp bạn trong việc này rồi.
- Ở trong phạm vi bài viết này thì mình muốn authorize cho model Post. Cú pháp như sau:
php artisan make:policy PostPolicy
- Mn chú ý là một policy bắt buộc phải có hậu tố là Policy đi theo sau model hoặc resource nhé.
- Nếu như muốn generate ra một file có cả CRUD thì mn chạy lệnh sau:
php artisan make:policy PostPolicy --model=Post
2. Đăng kí Policy:
- Bước tiếp theo bạn phải đăng kí policy. Việc đăng kí này giúp App mapping được giữa model của bạn với policy một cách tự động.
<?php
namespace App\Providers;
use App\Policies\PostPolicy;
use App\Post;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
Post::class => PostPolicy::class,
];
/**
* Register any application authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}
3. Triển khai policy
a) Policy methods
- Vừa rồi chúng ta chỉ mới setup một số thứ cơ bản, bây giờ mới đến lúc chúng thiết lập policy theo mong muốn của mình. Giả sử mình muốn phân quyền là User chỉ có quyền update những bài Post của User đó mà thôi:
- Chúng ta mở file PostPolicy.php, và thêm method update vào như dưới:
<?php
namespace App\Policies;
use App\Post;
use App\User;
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;
}
}
- Tên method ở policy bạn có thể đặt theo tùy thích không nhất thiết phải giống với method ở controller.
- Trường hợp không có model
/**
* Determine if the given user can create posts.
*
* @param \App\User $user
* @return bool
*/
public function create(User $user)
{
//
}
- Ở ví dụ trên là trường hợp create Post, lúc này không có đối tượng post thì mình chỉ cần 1 tham số là instance của class User cho method create.
- Policy filter:
Đối với một số user nhất định, bạn muốn họ được toàn quyền trong policy, thì lúc này bạn sử dụng method before ở đầu class Policy. Method này sẽ thực thi trước khi các hàm khác trong Policy.
public function before($user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}
- Dưới đây là bảng mapping giữa các method trong policy với controller
4. Các cách sử dụng policy
if ($user->can('update', $post)) {
//
}
- Sử dụng trong Middleware:
use App\Post;
Route::put('/post/{post}', function (Post $post) {
// The current user may update the post...
})->middleware('can:update,post');
- Sử dụng trong Controller:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Update the given blog post.
*
* @param Request $request
* @param Post $post
* @return Response
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
// The current user can update the blog post...
}
}
- Sử dụng Authorizing Resource trong Controller: Thay vì phải viết $this->authorize('update', $post); ở trừng action trong Controller thì Laravel hỗ trợ cho chúng 1 method cực hay authorizeResource. Method này sẽ add authorization tương ứng giữa Policy và Controller với nhau. Dưới đây là bảng mapping giữa các method trong 2 class Policy và Controller.
- Sử dụng ở Blade Templates:
@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 Cannot Update The Post -->
@elsecannot('create', App\Post::class)
<!-- The Current User Cannot Create A New Post -->
@endcannot
III.Tổng kết
- Bài viết này được tham khảo nhiều nguồn khác nhau: viblo, medium, laravel.