Bài toán phân chia quyền cho user là một bài toán rất phổ biến và thường gặp khi làm các dự án web. Đơn giản như với quyền admin thì có thể thực hiện một số thao tác mà user thông thường không thể thực hiện được. Việc phân chia quyền user, cũng đưa đến một nguy cơ chiếm quyền user và đưa quyền user lên mức cao hơn và từ quyền được chiếm, thì họ có thể phá hoại hoàn toàn dự án mà chúng ta đã xây dựng, hoặc lấy các thông tin user, cho một mục đích bất chính nào đó. Như vậy, việc phân chia quyền cho user, phải kiểm soát một cách chặt chẽ, và nếu không thực hiện một cách tỉ mỉ và cẩn thận, có thể dẫn đến vô số những nguy cơ cho sản phẩm mà chúng ta đưa ra. Thật may, laravel đã cung cấp cho chúng ta ba công cụ hỗ trợ để đơn giản hóa việc phân chia quyền user và định nghĩa các hành động mà user được phép hành động: Middleware, Gate, Policy
php artisan make:middleware CheckAge
Câu lệnh này sẽ tạo ra 1 class mới là CheckAge đặt trong thư mục app/Http/Middleware mà chúng ta đã đề cập đến ở trên<?php namespace App\Http\Middleware; use Closure; class CheckAge { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if ($request->age <= 200) { return redirect('home'); } return $next($request); } }
Mục đích của middleware trên là kiểm tra thông tin age (số tuổi) trong mỗi request, nếu thuộc tính này mà dưới 200, thì cho trở về trang ‘home’, nếu không, thì cho request thực hiện tiến trình của nó. Middleware này chủ yếu là tìm những người ngoài hành tinh hoặc những tiên nhân mới được phép sử dụng dịch vụ mà chúng ta cung cấp, tất cả mọi người bình thường thì không được phép dùng dịch vụ. Nếu diễn tả đơn giản công việc của middleware trên là, nếu có cụ nào sống trên 200 tuổi thì các cụ làm gì thì làm, nếu các cụ mà sống dưới 200 tuổi, thì mời trở về trang chủ đọc lại điều kiện sử dụng dịch vụ. Một middleware đậm chất tấu hài. Nếu số tuổi mà chúng ta đặt mốc là 18 tuổi, chúng ta sẽ có một middleware chỉ giành cho những thành viên trên 18 tuổi trở lên có thể truy cập các nội dung mà chúng ta đưa ra. Điều này nghe có vẻ thì hợp lý hơn nhiều.Tìm hiểu thêm về middleware tại đây\
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Auth;
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('edit-comment', function ($user, $commment) {
return $user->id == $comment->user_id;
});
}
}
public function index()
{
$comment = Comment::findOrFail(1); // comment có id = 1 có user_id = 1
if (Gate::allows('edit-comment', $comment)) {
echo "Ban co quyen chinh sua comment";
} else {
echo "Ban khong co quyen chinh sua comment";
}
}
Chúng ta có thể sử dụng allows hoặc denies từ Gate Facade để định nghĩa việc cho phép hay từ chối hành động của Gate, ở ví dụ trên ta cho phép hành động edit-comment. Và như đã đề cập ở trên, mặc định Gate sẽ nhận user đang đăng nhập là tham số thứ nhất, user, nên khi sử dụng Gate, ta chỉ truyền tham số comment như là tham số thứ 2.
php artisan make:policy PostPolicy --model=Post
Ta thêm –model=Post để báo cho Larvel tự động tạo các phương thức CRUD, ta có thể truy cập mọi policy theo đường dẫn app/Policies/ Ta có thể viết PostPolicy như sau
<?php
namespace App\Policies;
use App\User;
use App\Post;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
public function view(User $user, Post $post)
{
return TRUE;
}
public function create(User $user)
{
return $user->id > 0;
}
public function update(User $user, Post $post)
{
return $user->id == $post->user_id;
}
public function delete(User $user, Post $post)
{
return $user->id == $post->user_id;
}
}
Để sử dụng class Policy, thì chúng ta sẽ khai báo trong service provider của 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
{
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Post::class => PostPolicy::class,
];
public function boot()
{
$this->registerPolicies();
}
}
Rồi chúng ta có thể viết nó trong controller như sau
<?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()
{
// Người dùng hiện tại
$user = Auth::user();
// load post
$post = Post::find(1);
if ($user->can('view', $post)) {
echo "Người dùng được quyền xem";
} else {
echo 'Người dùng không được quyền xem.';
}
}
public function create()
{
// Người dùng hiện tại
$user = Auth::user();
if ($user->can('create', Post::class)) {
echo 'Được quyền.';
} else {
echo 'Không được quyền';
}
exit;
}
public function update()
{
// Người dùng hiện tại
$user = Auth::user();
// load post
$post = Post::find(1);
if ($user->can('update', $post)) {
echo "Được quyền";
} else {
echo 'Không được quyền.';
}
}
public function delete()
{
// Người dùng hiện tại
$user = Auth::user();
// load post
$post = Post::find(1);
if ($user->can('delete', $post)) {
echo "Được quyền";
} else {
echo 'Không được quyền.';
}
}
}
Cũng có thể sử dụng authorize của controller helpers.
You need to login in order to like this post: click here
YOU MIGHT ALSO LIKE