Phan quyen theo vai tro trong ASP.NET Core – Huong dan .NET 10

Trong bai viet nay, chung ta se trien khai phan quyen theo vai tro trong ASP.NET Core .NET 10: them vai tro vao JWT, bao ve cac endpoint Minimal API bang RequireRole va xu ly loi khi vai tro khong duoc anh xa dung.

Tom tat: Dua vai tro cua nguoi dung vao JWT duoi dang claim, cau hinh RoleClaimType de ASP.NET Core biet claim nao chua vai tro, sau do bao ve endpoint bang RequireAuthorization(p => p.RequireRole("Admin")) tren Minimal API hoac [Authorize(Roles = "Admin")] tren controller.

Xac thuc tra loi cau hoi “ban la ai?”. Phan quyen tra loi cau hoi “ban duoc phep lam gi?”. Trong bai viet ve xac thuc JWT, nguoi dung dang nhap va nhan token da ky. O day, chung ta se gioi han nhung tai nguyen ma moi nguoi dung dang nhap duoc phep truy cap dua tren vai tro.

Phan quyen theo vai tro la gi?

Phan quyen theo vai tro gioi han quyen truy cap den endpoint dua tren vai tro duoc gan cho nguoi dung. Vai tro la mot nhom co ten, chang han Admin, Manager hoac User. Endpoint se khai bao nhung vai tro nao duoc phep goi no.

Neu token cua nguoi goi chua vai tro phu hop, request duoc chap nhan. Neu khong, API tra ve 403 Forbidden.

Mo hinh nay thuong duoc goi la RBAC, viet tat cua Role-Based Access Control. Day la mo hinh truc quan: admin co the xoa du lieu, manager co the chinh sua, con nguoi dung thong thuong co the xem du lieu.

Vai tro di tu co so du lieu den endpoint nhu the nao?

Mot lan kiem tra vai tro lien quan den ba noi va ca ba phai thong nhat voi nhau:

  1. Kho Identity: ASP.NET Core Identity luu nguoi dung va vai tro trong cac bang AspNetUsers va AspNetRoles, hoac trong bo nho neu dung ban demo.
  2. JWT: Khi dang nhap, ung dung doc cac vai tro cua nguoi dung tu Identity va ghi tung vai tro vao token duoi dang claim.
  3. ClaimsPrincipal: Trong moi request, JWT bearer middleware xac minh token va tao lai nguoi dung tu cac claim. RequireRole va User.IsInRole() kiem tra doi tuong nay, khong truy van truc tiep co so du lieu.

Dieu nay dan den hai he qua quan trong:

  • Kiem tra vai tro khong truy cap co so du lieu. Sau khi token duoc phat hanh, cac vai tro ben trong token la nguon du lieu duoc su dung. Cach lam nay nhanh, khong can luu trang thai va phu hop voi JWT.
  • Vai tro trong token bi co dinh cho den lan dang nhap tiep theo. Neu nang quyen mot nguoi dung thanh Admin, token hien tai cua ho van chua thong tin cu. Ho can dang nhap lai de nhan token moi.

Thiet lap API mau

Vi du su dung ASP.NET Core Identity cho nguoi dung, JsonWebTokenHandler de tao token va EF Core InMemory de khong can cai dat co so du lieu.

Tinh huong la mot API quan ly kho san pham voi ba vai tro va ba tai khoan mau:

  • admin@codewithmukesh.com / Admin123! – Admin, Manager
  • manager@codewithmukesh.com / Manager123! – Manager
  • user@codewithmukesh.com / User123! – User

Tai khoan admin co ca hai vai tro de minh hoa truong hop yeu cau dong thoi nhieu vai tro.

Nen dat ten vai tro trong mot lop tinh de tranh loi go sai:

public static class Roles
{
    public const string Admin = "Admin";
    public const string Manager = "Manager";
    public const string User = "User";
}

Ten vai tro phan biet chu hoa va chu thuong khi tro thanh claim. admin va Admin la hai gia tri khac nhau.

Dat vai tro vao JWT

Khi dang nhap, doc danh sach vai tro tu Identity va them mot claim role cho moi vai tro:

var claims = new List<Claim>
{
    new(JwtRegisteredClaimNames.Sub, user.Id),
    new(JwtRegisteredClaimNames.Email, user.Email!),
    new(JwtRegisteredClaimNames.Name, $"{user.FirstName} {user.LastName}"),
    new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};

// Them mot claim role cho moi vai tro cua nguoi dung.
claims.AddRange(
    roles.Select(role => new Claim("role", role)));

Neu giai ma token cua manager, payload se co gia tri "role": "Manager". Token cua admin co the chua nhieu claim cung loai va duoc bieu dien thanh mang:

"role": ["Admin", "Manager"]

Vai tro khong phai la mot co che tach biet gan them vao token. Ve mat ky thuat, vai tro chi la mot claim voi ten da duoc thong nhat.

O phia nhan, ASP.NET Core can biet claim nao chua vai tro. Cau hinh dieu nay bang RoleClaimType:

.AddJwtBearer(options =>
{
    // Giu nguyen ten claim trong token.
    options.MapInboundClaims = false;

    options.TokenValidationParameters = new TokenValidationParameters
    {
        // Cau hinh issuer, audience va signing key nhu thong thuong.
        NameClaimType = JwtRegisteredClaimNames.Name,
        RoleClaimType = "role"
    };
});

O day, dich vu token ghi vai tro duoi ten role va middleware cung duoc cau hinh doc vai tro tu role. Hai phia phai khop nhau. Neu khong, moi lan kiem tra vai tro deu co the that bai voi 403.

Bao ve endpoint bang RequireRole

Sau khi vai tro da nam trong token va RoleClaimType duoc cau hinh, viec bao ve endpoint chi can mot dong:

public static void MapProductEndpoints(this IEndpointRouteBuilder app)
{
    var group = app.MapGroup("/api/products")
        .WithTags("Products")
        .RequireAuthorization();

    // Moi nguoi dung da dang nhap deu co the xem san pham.
    group.MapGet("/", (ProductStore store) =>
        Results.Ok(store.GetAll()));

    // Chi Admin duoc phep xoa.
    group.MapDelete("/{id:int}", (int id, ProductStore store) =>
            store.Delete(id)
                ? Results.NoContent()
                : Results.NotFound())
        .RequireAuthorization(policy =>
            policy.RequireRole(Roles.Admin));
}

Co hai lop bao ve dang ket hop:

  • RequireAuthorization() o cap group yeu cau nguoi goi phai dang nhap khi truy cap bat ky endpoint nao duoi /api/products.
  • RequireRole(Roles.Admin) o endpoint xoa them yeu cau nguoi goi phai co vai tro Admin.

Nguoi khong co token nhan 401 Unauthorized. Manager da dang nhap nhung goi DELETE se nhan 403 Forbidden.

401 co nghia API chua xac dinh duoc ban la ai. 403 co nghia API da biet chinh xac ban la ai nhung tu choi quyen truy cap.

Neu dung controller, cach viet tuong ung la:

[Authorize(Roles = "Admin")]
[HttpDelete("{id}")]
public IActionResult Delete(int id)
{
    // Xu ly xoa san pham.
}

Hai cach viet deu su dung cung mot co che phan quyen ben duoi. Chon cach phu hop voi phong cach cua du an.

Luu y thu tu middleware: UseAuthentication() phai chay truoc UseAuthorization(). Xac thuc xac dinh nguoi goi la ai; phan quyen quyet dinh nguoi do duoc lam gi.

Nhieu vai tro: OR hay AND?

Ket qua phu thuoc vao cach ban viet dieu kien.

Nhieu vai tro trong mot lan goi la OR

Chi can co mot trong cac vai tro duoc liet ke:

group.MapPost("/", (CreateProductRequest request, ProductStore store) =>
    {
        var product = store.Add(request);
        return Results.Created($"/api/products/{product.Id}", product);
    })
    .RequireAuthorization(policy =>
        policy.RequireRole(Roles.Admin, Roles.Manager));

Admin hoac Manager deu co the tao san pham. Tren controller, cach viet tuong ung la:

[Authorize(Roles = "Admin,Manager")]

Dau phay trong thuoc tinh tren co nghia la OR, khong phai AND.

Nhieu yeu cau tach biet la AND

Neu can nguoi goi co dong thoi ca hai vai tro, hay chain hai lan RequireRole:

group.MapGet("/audit", () =>
        Results.Ok("Bao cao kiem ke kho. Ban co ca Admin va Manager."))
    .RequireAuthorization(policy => policy
        .RequireRole(Roles.Admin)
        .RequireRole(Roles.Manager));

Tren controller, dat hai thuoc tinh:

[Authorize(Roles = "Admin")]
[Authorize(Roles = "Manager")]

Tai khoan admin trong vi du co ca Admin va Manager nen vuot qua yeu cau AND. Tai khoan manager chi co Manager nen bi tu choi voi 403.

Su dung lai kiem tra vai tro bang named policy

Neu mot kiem tra duoc dung o nhieu endpoint, hay dat ten cho policy va khai bao mot lan:

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ManagerOnly", policy =>
        policy.RequireRole(Roles.Manager));

Sau do tham chieu policy bang ten:

group.MapPut("/{id:int}/restock", (int id) =>
        Results.Ok($"Product {id} restocked."))
    .RequireAuthorization("ManagerOnly");

Khi y nghia cua ManagerOnly thay doi, moi endpoint su dung policy nay se tu dong ap dung quy tac moi. Thuc te, ca cac lan goi RequireRole truc tiep cung duoc chuyen thanh policy o ben duoi.

Kiem tra vai tro trong code voi User.IsInRole

Khong phai luc nao cung chi co hai ket qua cho phep hoac tu choi. Doi khi cung mot endpoint phuc vu du lieu khac nhau tuy theo vai tro:

group.MapGet("/dashboard", (ClaimsPrincipal user) =>
{
    var greeting = $"Hello {user.Identity?.Name}.";

    if (user.IsInRole(Roles.Admin))
    {
        return Results.Ok(
            $"{greeting} Full dashboard: sales, inventory, and user management.");
    }

    return user.IsInRole(Roles.Manager)
        ? Results.Ok(
            $"{greeting} Manager dashboard: inventory and restock queue.")
        : Results.Ok(
            $"{greeting} Your orders and saved items.");
});

IsInRole("Admin") chi don gian hoi xem ClaimsPrincipal co claim vai tro voi gia tri Admin hay khong.

Quy tac thuc te:

  • Dung RequireRole khi ket qua la cho phep hoac tu choi truy cap.
  • Dung IsInRole khi can hien thi noi dung khac nhau cho tung vai tro.

Neu cac chuoi IsInRole tro nen dai va dung de chan truy cap, logic do nen duoc chuyen vao policy.

Thu nghiem cac quy tac vai tro

Chay ung dung bang dotnet run --project RoleBasedAuth.Api, sau do mo Scalar UI tai /scalar/v1 hoac dung file requests.http.

  • GET /api/products khong co token – 401 Unauthorized.
  • GET /api/products voi tai khoan User – 200 OK.
  • POST /api/products voi tai khoan Manager – 201 Created.
  • POST /api/products voi tai khoan User – 403 Forbidden.
  • DELETE /api/products/1 voi tai khoan Manager – 403 Forbidden.
  • DELETE /api/products/1 voi tai khoan Admin – 204 No Content.
  • GET /api/products/audit voi tai khoan Manager – 403 Forbidden.
  • GET /api/products/audit voi tai khoan Admin – 200 OK.

Vi sao vai tro cua toi khong hoat dong?

Loi pho bien nhat la token ro rang co vai tro nhung moi kiem tra deu tra ve 403. Nguyen nhan thuong nam o viec anh xa ten claim.

Trong mot so cau hinh cu, khi MapInboundClaims la true, ten claim den tu JWT co the bi doi sang dang URI dai. Claim role co the tro thanh:

http://schemas.microsoft.com/ws/2008/06/identity/claims/role

Trong khi do, RequireRole lai tim vai tro theo gia tri cua RoleClaimType. Neu hai ten khac nhau, middleware khong tim thay vai tro. Khong co exception ro rang, chi co ket qua 403.

Ba thanh phan phai thong nhat:

  1. Ten claim duoc ghi khi tao token, vi du role.
  2. MapInboundClaims = false de middleware khong tu y doi ten claim.
  3. RoleClaimType = "role" de cac kiem tra doc dung claim.

De chan doan nhanh, tao tam mot endpoint hien thi cac claim ma server dang nhin thay:

group.MapGet("/debug/claims", (ClaimsPrincipal user) =>
    Results.Ok(user.Claims.Select(c => new { c.Type, c.Value })))
    .RequireAuthorization();

Goi endpoint bang token dang loi. Neu Type cua claim vai tro la mot URL dai thay vi role, ban da tim ra nguyen nhan. Xoa endpoint debug nay truoc khi dua ung dung len moi truong that.

Mot so truong hop khac:

  • Moi request deu bi 403, ke ca dang nhap: Kiem tra xem ban co dat RequireAuthorization() len group chua endpoint dang nhap hay khong. Endpoint dang nhap phai cho phep truy cap an danh.
  • Da them vai tro nhung van bi 403: Token hien tai duoc tao truoc khi thay doi vai tro. Hay dang nhap lai de lay token moi.
  • Chay duoc tren Scalar nhung loi tu SPA: Nguyen nhan thuong la CORS tu choi preflight truoc khi yeu cau den buoc phan quyen.

Khi nao kiem tra theo vai tro khong con phu hop?

Vai tro phu hop de mo ta cac nhom nguoi dung lon va on dinh. Tuy nhien, vai tro khong phu hop voi cac quyen chi tiet.

Ban dau he thong co Admin, Manager va User. Sau do nghiep vu yeu cau manager duoc restock nhung khong duoc tao san pham. Ban them SeniorManager. Tiep theo la CustomerAdmin, OrderAdmin, RegionalLead va hang loat vai tro khac.

Khi danh sach vai tro tang tu 3 len 15, cac endpoint bat dau co cac dieu kien dai nhu:

RequireRole("Admin", "OrderAdmin", "SeniorManager", "RegionalLead")

Luc nay, rat kho tra loi cau hoi “RegionalLead duoc lam gi?” ma khong doc toan bo codebase.

Vai tro mo ta nguoi dung la ai. Claims va policy mo ta nguoi dung co the lam gi. Neu ban tao mot vai tro chi de dai dien cho mot kha nang rieng le, do la dau hieu nen chuyen sang claims-based authorization hoac policy-based authorization.

Phan quyen theo vai tro la lua chon tot khi he thong co khong qua nhieu nhom on dinh va quy tac don gian: nhom nay duoc phep, nhom kia khong duoc phep.

Cac diem can nho

  • Phan quyen theo vai tro gioi han endpoint dua tren thanh vien vai tro.
  • Minimal API dung RequireRole; controller dung [Authorize(Roles = "...")].
  • Vai tro trong JWT chi la mot claim voi ten da thong nhat.
  • RoleClaimType phai trung voi ten claim ma dich vu tao token ghi vao.
  • Nhieu vai tro trong mot lan goi RequireRole co nghia OR.
  • Nhieu lan goi RequireRole tach biet co nghia AND.
  • Thay doi vai tro can token moi de co hieu luc.
  • Dung named policy khi mot kiem tra vai tro duoc lap lai o nhieu endpoint.
  • Khi ten vai tro bat dau dai dien cho tung kha nang rieng le, hay chuyen sang claims.

Cau hoi thuong gap

Phan quyen theo vai tro trong ASP.NET Core la gi?

Day la cach gioi han quyen truy cap API dua tren vai tro duoc gan cho nguoi dung, vi du Admin hoac Manager. Vai tro duoc truyen trong token xac thuc duoi dang claim va duoc kiem tra bang RequireRole tren Minimal API hoac thuoc tinh Authorize tren controller.

Lam the nao de them vai tro vao JWT?

Khi tao token luc dang nhap, doc vai tro tu kho nguoi dung, vi du bang UserManager.GetRolesAsync, sau do them mot claim cho moi vai tro. Cuoi cung, dat RoleClaimType trung voi ten claim da dung.

Vi sao vai tro khong hoat dong voi JWT?

Thuong la ten claim trong token khong trung voi RoleClaimType. Hay dat MapInboundClaims thanh false va su dung cung mot ten claim, vi du role, o ca luc tao token lan luc xac minh.

Nhieu vai tro trong Authorize la AND hay OR?

Nhieu vai tro trong cung mot thuoc tinh hoac cung mot lan goi RequireRole la OR. De yeu cau tat ca vai tro, hay dat nhieu thuoc tinh Authorize hoac chain nhieu lan RequireRole.

Khac nhau giua role va claim la gi?

Claim la cap ten-gia tri mo ta nguoi dung, chang han email hoac phong ban. Role ve mat ky thuat cung la mot claim, nhung co y nghia dac biet de mo ta nhom ma nguoi dung thuoc ve. Role phu hop voi nhom lon; claim phu hop voi thuoc tinh va kha nang chi tiet.

Vi sao toi nhan 403 thay vi 401?

401 co nghia yeu cau chua duoc xac thuc, token thieu hoac khong hop le. 403 co nghia xac thuc da thanh cong nhung nguoi dung khong co quyen can thiet.

Lam the nao de bao ve Minimal API theo vai tro trong .NET 10?

Goi RequireAuthorization tren endpoint hoac route group. Kiem tra dang nhap don thuan dung RequireAuthorization(). Kiem tra vai tro dung:

.RequireAuthorization(policy =>
    policy.RequireRole("Admin"));

Neu quy tac duoc dung lai, dang ky named policy bang AddAuthorizationBuilder() va tham chieu policy bang ten.

Ket luan

Ban da co mo hinh phan quyen theo vai tro day du cho Web API .NET 10: vai tro duoc tao boi ASP.NET Core Identity, truyen trong JWT duoi dang claims va duoc ap dung bang RequireRole hoac named policy.

Dieu quan trong nhat can nho la RoleClaimType phai khop voi ten claim trong token. Ngoai ra, can phan biet ro:

  • 401 la van de xac thuc.
  • 403 la van de phan quyen.
  • Nhieu vai tro trong mot lan goi la OR.
  • Nhieu yeu cau tach biet la AND.
  • Thay doi vai tro chi co hieu luc voi token moi.

Phan quyen theo vai tro la diem khoi dau tot cho cac he thong co mo hinh quyen don gian. Khi can mo ta cac kha nang chi tiet hon, hay chuyen sang claims-based authorization va policy-based authorization.

Chuc ban lap trinh vui ve!