
Written on 13th April 2026 by Carter Phan.
Authentication là quá trình xác minh danh tính người dùng (username/email + password) để cho phép truy cập hệ thống.
Các loại Authentication:
Authorization diễn ra sau khi authentication thành công, dùng để xác định:
⇒ người dùng được phép làm gì và truy cập tài nguyên nào.
Ví dụ: đọc file, sửa dữ liệu, truy cập API...
| Authentication | Authorization |
| Xác nhận danh tính của bạn để cấp quyền truy cập vào hệ thống. | Xác định xem bạn có được phép truy cập tài nguyên không. |
| Xác nhận thông tin đăng nhập để có quyền truy cập của người dùng. | Xác minh xem có cho phép truy cập hay không. |
| Dùng để login | Dùng để xem quyền hạn dựa trên role / permission |
| Xảy ra trước | Xảy ra sau |
Có 2 cách để authorize trong Laravel: Gates và Policies. Đầu tiên chúng ta sẽ đi tìm hiểu về Gates trong Laravel
Gate theo mình hiểu thì hầu hết dùng trong việc chúng ta authorize (xác thực) các action riêng lẻ. Ta sẽ định nghĩa các rằng buộc trong method boot của AuthServiceProvider và sử dụng facade Gate. Do là chúng ta xác thực xem người dùng này có được làm hành động hay truy cập vào trang này trang nọ trong hệ thống của chúng ta hay không nên đối số đầu tiên trong hàm rằng buộc sẽ là một user instance, còn đối số thứ hai sẽ là một instance khác. Ví dụ như người dùng sẽ có quyền thay đổi cập nhật comment của mình chẳng hạn
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;
});
}
}
Gate::define() sẽ định nghĩa một điều kiện giữa người dùng và thông tin commment, tức là nếu nó trả về true thì người dùng được phép sửa comment và ngược lại thì không được sửa.
Và để cho phép authorized thì trong controller chúng ta sẽ dùng câu lệnh sau :
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";
}
}
Trên chỉ là một ví dụ minh họa cho việc xem bạn có quyền chỉnh sửa comment không. Các bạn sẽ không phải truyền vào argument $user đầu tiên vào, Laravel sẽ tự động truyền user đang truy cập hệ thống vào trong Gate Closure. Gate::denies() ngược lại với Gate::allows().
Nếu bạn muốn xem một người dùng bất kỳ có được xác thực để thực hiện 1 action trong hệ thống của các bạn hay không thì các bạn có thể dùng phương thức forUser trong Gate facade
if (Gate::forUser($user)->allows('edit-comment', $comment)) {
echo "Người dùng này được phép chỉnh sửa comment";
}
if (Gate::forUser($user)->denies('edit-comment', $comment)) {
echo "Người dùng này không được phép chỉnh sửa comment";
}
Ở phiên bản Laravel 5.6 thì chúng ta có thêm Gate::before() để ta có thể cấp tất cả các quyền cho một người dùng nào đó trước khi các authorization được check. Thường thường thì đó chính là người quản trị website có tất cả các quyền trong hệ thống.
Gate::before(function ($user, $ability) {
if ($user->isSuperAdmin()) {
return true;
}
});
Và bạn có thể sử dụng Gate::after() để định nghĩa 1 callback để được thực thi sau mỗi lẩn kiểm tra authorization. Tuy nhiên, các bạn sẽ không thay đổi được kết quả của sự kiểm tra phân quyền.
Gate::after(function ($user, $ability, $result, $arguments) {
});
Policies là các class quản lý logic trong phân quyền liên quan đến Model hoặc tài nguyên nào đó. Ví dụ, các bạn có model Comment và một policy CommentPolicy để phân quyền xem người dùng nào sẽ được chỉnh sửa hay cập nhật comment của mình.
Tiếp theo để đăng ký 1 policy thì ta sẽ đăng ký trong file AuthServiceProvider.php. Đăng ký một policy sẽ chỉ dẫn cho Laravel biết policy nào sẽ được sử dụng để phân quyền hành động cho model nào:
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
Comment::class => CommentPolicy::class,
];
/**
* Register any application authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
}
}
Nếu trên mình đã nói Gate nó dùng để authorize những hành động riêng lẻ. Bây giờ viết trong Policy cũng không khác gì cả nhé, thay vì viết
Gate::define('edit-comment', function ($user, $commment) {
return $user->id == $comment->user_id;
});
ở trong function boot() bây giờ chúng ta sẽ viết trong policy như sau
class PostPolicy
{
/**
* Determine if the given post can be updated by the user.
* @return bool
*/
public function update(User $user, Comment $comment)
{
return $user->id === $comment->user_id;
}
}
Đôi với một người dùng nhất định trong hệ thống giả dụ như admin, người đó có tất cả các quyền mà không cần trải qua các authorize riêng lẻ. Vì vậy chúng ta sẽ định nghĩa một phương thức before trong policy. Phương thức này sẽ thực thi trước bất kỳ phương thức nào trong policy.
public function before($user, $ability)
{
if ($user->isAdmin()) {
return true;
}
}
Nếu bạn muốn một user không được phép thực hiện bất kỳ gì bạn chỉ cần trả về false trong phương thức before. Nếu giá trị được trả về là null, việc cấp quyền sẽ được tiếp tục diễn ra trong phương thức policy.
Rồi tiếp theo để thực hiện hành động authorize sử dụng Policy thế nào? Thì chúng ta sẽ thông qua 2 phương thức can và cant được tạo sẵn trong Model User. Phương thức can nhận hành động bạn muốn cấp phép và model liên quan và ngược lại là phương thức cant.
if ($user->can('update', $comment)) {
//
}
Laravel thêm một middleware có thể authorize action trước khi có request gửi đến ngay cả đến với routes hoặc controller. Mặc định, middleware Illuminate\Auth\Middleware\Authorize được gán key can trong class App\Http\Kernel
use App\Post;
Route::put('/post/{post}', function (Post $post) {
// The current user may update the post...
})->middleware('can:update,post');
Như ta đã biết, ngoài phương thức can ra thì Laravel còn hỗ trợ phương thức authorize do controller làm việc của chúng ta kế thừa từ App\Http\Controlers\Controller
class CommentController extends Controller
{
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Comment $comment)
{
$this->authorize('update', $comment);
// Người dùng có thể update commmet của mình
}
}
Khi viết Blade template, bạn chỉ muốn những người dùng chỉ có thể xem được những hành động mà người dùng có quyền truy cập thì chúng ta sẽ sử dụng @can và @cannot.
@can('update', $post)
// hiển thị button edit
@endcan
@cannot('update', $post)
// Khong hiển thị button edit
@endcannot