Gyakorlat – Jogcímek használata szabályzatalapú engedélyezéssel
Az előző leckében megismerte a hitelesítés és az engedélyezés közötti különbséget. Azt is megtanulta, hogyan használják a jogcímeket a szabályzatok az engedélyezéshez. Ebben a leckében az Identity használatával jogcímeket tárolhat, és szabályzatokat alkalmazhat a feltételes hozzáféréshez.
A pizzalista védelme
Új követelményt kapott, hogy a Pizzalista lap csak a hitelesített felhasználók számára legyen látható. Emellett csak rendszergazdák hozhatnak létre és törölhetnek pizzákat. Zárjuk le.
A Pages/Pizza.cshtml.cs fájlban alkalmazza a következő módosításokat:
Adjon hozzá egy
[Authorize]
attribútumot aPizzaModel
osztályhoz.[Authorize] public class PizzaModel : PageModel
Az attribútum a lap felhasználói engedélyezési követelményeit ismerteti. Ebben az esetben nincs más követelmény, csak hogy a felhasználó hitelesítve legyen. A névtelen felhasználók nem tekinthetik meg a lapot, és a rendszer átirányítja a bejelentkezési lapra.
A hivatkozás feloldásához
Authorize
adja hozzá a következő sort ausing
fájl tetején található irányelvekhez:using Microsoft.AspNetCore.Authorization;
Adja hozzá a következő tulajdonságot a
PizzaModel
osztályhoz:[Authorize] public class PizzaModel : PageModel { public bool IsAdmin => HttpContext.User.HasClaim("IsAdmin", bool.TrueString); public List<Pizza> pizzas = new();
A fenti kód határozza meg, hogy a hitelesített felhasználó
True
értékűIsAdmin
jogcímmel rendelkezik-e. Ennek a kiértékelésnek az eredménye egyIsAdmin
nevű csak olvasható tulajdonságban érhető el.Adja hozzá
if (!IsAdmin) return Forbid();
a ésOnPostDelete
aOnPost
metódus elejéhez:public IActionResult OnPost() { if (!IsAdmin) return Forbid(); if (!ModelState.IsValid) { return Page(); } PizzaService.Add(NewPizza); return RedirectToAction("Get"); } public IActionResult OnPostDelete(int id) { if (!IsAdmin) return Forbid(); PizzaService.Delete(id); return RedirectToAction("Get"); }
A következő lépésben elrejti a létrehozási/törlési felhasználói felület elemeit a nem rendszergazdák számára. Ez nem akadályozza meg, hogy egy támadó egy olyan eszközzel, mint a HttpRepl vagy a Postman közvetlenül hozzáférjen ezekhez a végpontokhoz. Az ellenőrzés hozzáadásával biztosítható, hogy ha ez megkísérlése történik, a rendszer HTTP 403-állapotkódot ad vissza.
A Pages/Pizza.cshtml fájlban adjon hozzá ellenőrzéseket a rendszergazdai felhasználói felület elemeinek elrejtéséhez a nem rendszergazdák elől:
Új pizza űrlap elrejtése
<h1>Pizza List 🍕</h1> @if (Model.IsAdmin) { <form method="post" class="card p-3"> <div class="row"> <div asp-validation-summary="All"></div> </div> <div class="form-group mb-0 align-middle"> <label asp-for="NewPizza.Name">Name</label> <input type="text" asp-for="NewPizza.Name" class="mr-5"> <label asp-for="NewPizza.Size">Size</label> <select asp-for="NewPizza.Size" asp-items="Html.GetEnumSelectList<PizzaSize>()" class="mr-5"></select> <label asp-for="NewPizza.Price"></label> <input asp-for="NewPizza.Price" class="mr-5" /> <label asp-for="NewPizza.IsGlutenFree">Gluten Free</label> <input type="checkbox" asp-for="NewPizza.IsGlutenFree" class="mr-5"> <button class="btn btn-primary">Add</button> </div> </form> }
A Pizza törlése gomb elrejtése
<table class="table mt-5"> <thead> <tr> <th scope="col">Name</th> <th scope="col">Price</th> <th scope="col">Size</th> <th scope="col">Gluten Free</th> @if (Model.IsAdmin) { <th scope="col">Delete</th> } </tr> </thead> @foreach (var pizza in Model.pizzas) { <tr> <td>@pizza.Name</td> <td>@($"{pizza.Price:C}")</td> <td>@pizza.Size</td> <td>@Model.GlutenFreeText(pizza)</td> @if (Model.IsAdmin) { <td> <form method="post" asp-page-handler="Delete" asp-route-id="@pizza.Id"> <button class="btn btn-danger">Delete</button> </form> </td> } </tr> } </table>
Az előző módosítások miatt a csak rendszergazdák számára elérhető felhasználói felületi elemek csak akkor lesznek megjelenítve, ha a hitelesített felhasználó rendszergazda.
Engedélyezési szabályzat alkalmazása
Van még egy dolog, amit le kellene záratnia. Van egy lap, amely csak a rendszergazdák számára érhető el, egyszerűen Pages/AdminsOnly.cshtml néven. Hozzunk létre egy szabályzatot a IsAdmin=True
jogcím ellenőrzéséhez.
A Program.cs fájlban végezze el a következő módosításokat:
Szúrja be az alább kiemelt kódot:
// Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddTransient<IEmailSender, EmailSender>(); builder.Services.AddSingleton(new QRCodeService(new QRCodeGenerator())); builder.Services.AddAuthorization(options => options.AddPolicy("Admin", policy => policy.RequireAuthenticatedUser() .RequireClaim("IsAdmin", bool.TrueString))); var app = builder.Build();
A fenti kód egy
Admin
nevű engedélyezési szabályzatot definiál. A szabályzat megköveteli, hogy a felhasználó hitelesítve legyen, ésTrue
értékűIsAdmin
jogcímmel rendelkezzen.Módosítsa a hívást
AddRazorPages
a következőre:builder.Services.AddRazorPages(options => options.Conventions.AuthorizePage("/AdminsOnly", "Admin"));
A
AuthorizePage
metódushívás a szabályzat alkalmazásával biztosítja a /AdminsOnly Razor-oldal útvonalátAdmin
. Azoknak a hitelesített felhasználóknak, akik nem tesznek eleget a szabályzat követelményeinek, a Hozzáférés megtagadva üzenet jelenik meg.Tipp
Másik lehetőségként módosíthatja az AdminsOnly.cshtml.cs fájlt. Ebben az esetben attribútumként kell hozzáadnia
[Authorize(Policy = "Admin")]
aAdminsOnlyModel
osztályhoz. A fent bemutatott megközelítés egyik előnyeAuthorizePage
, hogy a védelem alatt álló Razor-oldal nem igényel módosításokat. Az engedélyezési szempont kezelése ehelyett a Program.cs fájlban történik.
A Pages/Shared/_Layout.cshtml fájlban foglalja bele a következő módosításokat:
<ul class="navbar-nav flex-grow-1"> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-page="/Pizza">Pizza List</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a> </li> @if (Context.User.HasClaim("IsAdmin", bool.TrueString)) { <li class="nav-item"> <a class="nav-link text-dark" asp-area="" asp-page="/AdminsOnly">Admins</a> </li> } </ul>
Az előző módosítás feltételesen elrejti az Rendszergazda hivatkozást a fejlécben, ha a felhasználó nem rendszergazda.
IsAdmin
Jogcím hozzáadása egy felhasználóhoz
Annak megállapításához, hogy mely felhasználóknak kell megkapniuk a IsAdmin=True
jogcímet, az alkalmazás egy megerősített e-mail-címre fog támaszkodni a rendszergazda azonosításához.
Az appsettings.json fájlban adja hozzá a kiemelt tulajdonságot:
{ "AdminEmail" : "admin@contosopizza.com", "Logging": {
Ez az a megerősített e-mail-cím, amely hozzárendeli a jogcímet.
A Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs területen hajtsa végre a következő módosításokat:
Szúrja be az alább kiemelt kódot:
public class ConfirmEmailModel : PageModel { private readonly UserManager<RazorPagesPizzaUser> _userManager; private readonly IConfiguration Configuration; public ConfirmEmailModel(UserManager<RazorPagesPizzaUser> userManager, IConfiguration configuration) { _userManager = userManager; Configuration = configuration; }
Az előző módosítás módosítja a konstruktort, hogy az IoC-tárolótól kapjon egy
IConfiguration
értéket. AIConfiguration
az appsettings.json fájl értékeit tartalmazza, és egy nevű írásvédett tulajdonsághozConfiguration
van rendelve.Alkalmazza a kiemelt módosításokat az
OnGetAsync
metódusra:public async Task<IActionResult> OnGetAsync(string userId, string code) { if (userId == null || code == null) { return RedirectToPage("/Index"); } var user = await _userManager.FindByIdAsync(userId); if (user == null) { return NotFound($"Unable to load user with ID '{userId}'."); } code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); var result = await _userManager.ConfirmEmailAsync(user, code); StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email."; var adminEmail = Configuration["AdminEmail"] ?? string.Empty; if(result.Succeeded) { var isAdmin = string.Compare(user.Email, adminEmail, true) == 0 ? true : false; await _userManager.AddClaimAsync(user, new Claim("IsAdmin", isAdmin.ToString())); } return Page(); }
A fenti kód a következőket végzi el:
- A
AdminEmail
sztring beolvasva aConfiguration
tulajdonságból, és hozzá lesz rendelve a következőhözadminEmail
: . - A null-coalescing operátort
??
használja annak ellenőrzéséreadminEmail
, hogystring.Empty
az érték értékre van-e állítva, ha nincs megfelelő érték az appsettings.json fájlban. - Ha a felhasználó e-mail-címe sikeresen megerősítést nyert:
- A rendszer összehasonlítja a felhasználó címét a következőhöz
adminEmail
: .string.Compare()
a kis- és nagybetűket nem megkülönböztető összehasonlításhoz használatos. - A
UserManager
osztályAddClaimAsync
metódusa lesz meghívva egyIsAdmin
jogcím mentéséhez azAspNetUserClaims
táblába.
- A rendszer összehasonlítja a felhasználó címét a következőhöz
- A
A fájl elejére szúrja be a következő kódot. Feloldja az
Claim
osztályhivatkozásokat aOnGetAsync
metódusban:using System.Security.Claims;
Adminisztrátori jogcím tesztelése
Lássunk egy utolsó tesztet az új rendszergazdai funkció ellenőrzéséhez.
Győződjön meg arról, hogy az összes módosítást mentette.
Futtassa az alkalmazást a következővel:
dotnet run
.Nyissa meg az alkalmazást, és jelentkezzen be egy meglévő felhasználóval, ha még nincs bejelentkezve. Válassza a Pizzalista elemet a fejlécből. Figyelje meg, hogy a felhasználó nem mutat be felhasználói felületi elemeket a pizzák törléséhez vagy létrehozásához.
A fejlécben nincs Rendszergazda hivatkozás. A böngésző címsorában lépjen közvetlenül a RendszergazdákOnly lapra. Cserélje le
/Pizza
az URL-címet a következőre:/AdminsOnly
.A felhasználó számára tiltva van az oldal megnyitása. A Hozzáférés megtagadva üzenet jelenik meg.
Válassza a Kijelentkezés lehetőséget.
Regisztráljon egy új felhasználót a következő címmel
admin@contosopizza.com
: .A korábbiakhoz hasonlóan erősítse meg az új felhasználó e-mail-címét, és jelentkezzen be.
Miután bejelentkezett az új rendszergazda felhasználóval, válassza a Pizzalista hivatkozást a fejlécben.
A rendszergazda létrehozhat és törölhet pizzákat.
A fejlécben válassza a Rendszergazdák hivatkozást.
Megjelenik az AdminsOnly lap.
Az AspNetUserClaims tábla vizsgálata
Futtassa a következő lekérdezést a VS Code SQL Server bővítményével:
SELECT u.Email, c.ClaimType, c.ClaimValue
FROM dbo.AspNetUserClaims AS c
INNER JOIN dbo.AspNetUsers AS u
ON c.UserId = u.Id
Ekkor megjelenik egy lap az alábbihoz hasonló eredményekkel:
Jogcímtípus | ClaimValue | |
---|---|---|
admin@contosopizza.com | IsAdmin | Igaz |
Az IsAdmin
jogcím kulcs-érték párként van tárolva az AspNetUserClaims
táblában. Az AspNetUserClaims
rekord az AspNetUsers
táblában lévő felhasználói rekorddal van társítva.
Összefoglalás
Ebben az egységben úgy módosította az alkalmazást, hogy jogcímeket tároljon, és szabályzatokat alkalmazzon a feltételes hozzáféréshez.