- Cấu hình ConfigureApplicationCookie
- Role-based Authorization trong .NET
- [Authorize] : Chứng thực đơn giản
- [Authorize] : Chứng thực theo Role
Bài này tiếp tục thực hành, phát triển trên dự án của ví dụ Album trước: Identity (6) - Role trong Identity
Cấu hình Cookie cho Identity
Thực hiện thêm cấu hình sau vào ConfigureServices
, thêm sau AddIdentity
services.ConfigureApplicationCookie (options => { // options.Cookie.HttpOnly = true; // options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.LoginPath = $"/login/"; options.LogoutPath = $"/logout/"; options.AccessDeniedPath = $"/Identity/Account/AccessDenied"; });
Trong đó /login/
là URL để login, thay bằng Url ứng dụng của bạn (Areas/Identity/Pages/Account/Login.cshtml), trang này để ứng dụng chuyển hướng đến nếu
truy cập chức năng nào đó cần User phải đăng nhập. /Identity/Account/AccessDenied
trang ứng dụng chuyển hướng đến nếu User truy cập chức năng nào đó mà không được phân quyền (không
có role được phép truy cập)
Role-based Authorization trong ASP.NET
Role-based Authorization - chứng thực quyền dựa theo Role (vai trò) là cách xác định quyền đơn giản - cơ bản nhất của ASP.NET, cơ bản quyền của User dựa vào Role được gán cho User đó.
Để sử dụng ta dùng đến thuộc tính [Authorize], chỉ thị này áp dụng được cho Controller, Action của Controller, PageModel để xác định ai được quyền truy cập Controller, Action của Controller hay PageModel.
Lưu ý: Với Razor Page - thuộc tính [Authorize]
chỉ áp dụng ở mức độ lớp PageModel - không đến mức các Handler. Còn với Controller thì có từ mức
cả Controller hay chi tiết đến Action.
[Authorize] đơn giản
Sử dụng [Authorize] có vài tham số, ở trường hợp đơn giản nhất là không có tham số nào. Ở trường hợp này nó cho biết controller, action hay Page Razor chỉ cho các user đã xác thực (đăng ký và đăng nhập) được phép truy cập.
- Thuộc tính [Authorize] áp dụng cho lớp Controller - thì mọi Action trong Controller ảnh hưởng
- [Authorize] áp dụng cho Action thì Action bị ảnh hưởng
- [Authorize] áp dụng cho PageModel thì tất cả các Handler bị ảnh hưởng (không áp dụng được cho từng Handler)
Ví dụ tạo ra một Razor Page như sau: TestAuthorize1
Pages/TestAuthorize1.cshtml
namespace Album.Pages { [Authorize] public class TestAuthorize1Model : PageModel { public void OnGet() { } } }
Pages/TestAuthorize1.cshtml.cs
@page "/test-authorize-1/" @inject Microsoft.AspNetCore.Identity.UserManager<Album.Models.AppUser> UserManager @model Album.Pages.TestAuthorize1Model <p class="alert alert-danger">@UserManager.GetUserName(User), Bạn đang truy cập TestAuthorize1</p>
Do khai báo [Authorize]. Truy cập vào /test-authorize-1/
nếu đang đăng nhập thì truy cập được trang
Nếu không đăng nhập thì mọi truy vấn đến các handler của PageModel trên bị không thực hiện được mà nó sẽ tự chuyển về trang login đã cấu hình của Identity
Đối với mô hình MVC khi áp dụng [Authorize] ở tên lớp Controller thì mọi action chịu tác động chứng thực quyền. Đôi khi muốn một Action nào đó bỏ qua kiểm tra quyền thì sử dụng thuộc tính [AllowAnonymous], Ví dụ:
[Authorize] // Mọi action đều kiểm tra user đăng nhập mới thực hiện public class AccountController : Controller { [AllowAnonymous] // Cho phép User truy cập Action này mà không cần đăng nhập public ActionResult Action1() { } public ActionResult Action2() { } /... }
Hiên nay ASP.NET không có kế hoạch hỗ trợ [Authorize] trên các Handler của Razor Page, trong trường hợp như vậy bạn có thể chuyển sang dùng Controller của MVC hoặc
xây dựng một thuộc tính đặt tên AuthorizePageHandler
, mã nguồn của nó tại
AuthorizeIndexPageHandlerFilter, thì lúc này bạn có thể khai báo
chứng thực vào các Handler với [AuthorizePageHandler]
[Authorize] chứng thực theo Role
Bằng cách sử dụng thuộc tính Roles
của [Authorize]
gán bằng tên các role, thì nó sẽ kiểm tra User phải đăng nhập - user phải có Role liệt
kê trong Roles thì mới được truy cập
Ví dụ:
[Authorize(Roles = "Admin")] public class TestAuthorize1Model : PageModel { / .. }
Truy cập Page trên User phải được gán Role là Admin
Bạn có thể liệt kê các Role ví dụ: những User có Role Admin và Editor được truy cập
[Authorize(Roles = "Admin,Editor")]
Nếu bạn sử dụng nhiều dòng [Authorize(Roles = "RoleName")] thì User phải được gán tất cả các role đó (thuộc nhóm). Ví dụ User vừa thuộc nhóm Admin vừa thuộc Editor mới được truy cập
[Authorize(Roles = "Admin")] [Authorize(Roles = "Editor")] public class TestAuthorize1Model : PageModel { }
Trong Controller bạn có thể thiết lập bổ sung [Authorize] cho Action. Ví dụ:
[Authorize(Roles = "Admin, Editor")] public class MyController : Controller { public ActionResult ActionA() { } [Authorize(Roles = "Admin")] public ActionResult ActionnB() { } }
User thuộc nhóm Admin, Editor được truy cập Controller MyController, nhưng đến Action ActionB thì chỉ nhóm Admin được truy cập
Nếu một User không có Role chứng thực được truy cập thì nó sẽ chuyển hướng
về trang thiết lập trong AccessDeniedPath
đã cấu hình trong ConfigureServices
của Startup
services.ConfigureApplicationCookie (options => { /... options.AccessDeniedPath = $"/Identity/Account/AccessDenied"; });
Lưu ý: Khi bạn cập nhật Role cho một User nào đó - nếu User đó đang đăng nhập, chưa hết phiên làm việc thì thông tin mới vẫn chưa tác động vào User. Nếu muốn - thời gian nạp lại thông tin User từ Db ngắn hơn thì cấu hình thêm về SecurityStampValidatorOptions trong ConfigureServices như sau:
Tham khảo code ASP_NET_CORE/Album
services.Configure<SecurityStampValidatorOptions>(options => { // Trên 30 giây truy cập lại sẽ nạp lại thông tin User (Role) // SecurityStamp trong bảng User đổi -> nạp lại thông tinn Security options.ValidationInterval = TimeSpan.FromSeconds(30); });