CTI — Dezvoltarea Aplicațiilor Web — Laborator 7
Autentificare și Autorizare cu ASP.NET Core Identity
Obiective
Laboratorul continuă proiectul News Portal din Lab 6. La finalul acestui laborator, aplicația va avea user registration, login și role-based access control.
Obiectivele laboratorului:
- Instalarea și configurarea ASP.NET Core Identity
- Crearea
ApplicationUsercare extindeIdentityUser - Modificarea
AppDbContextpentru a moșteniIdentityDbContext - Implementarea Register, Login și Logout cu MVC
- Crearea și seeding-ul rolurilor: Admin, User
- Conceptul de Vizitator — utilizatorul neautentificat
- Atributul
[Authorize]pentru protejarea controller actions - Proprietatea conținutului: doar autorul sau admin-ul poate edita/șterge
Recapitulare Lab 6
Din laboratorul anterior avem:
- Modelele:
Article,Category,UsercuBaseEntity IArticleService/ArticleService,ICategoryService/CategoryServiceIUnitOfWork/UnitOfWork, Repository PatternArticlesControllerMVC cu Views și ViewModelsHomeController, paginare,IUserService/UserService
Autentificare vs Autorizare
| Concept | Întrebare | Exemplu |
|---|---|---|
| Autentificare | Cine ești? | Login cu email și parolă |
| Autorizare | Ce ai voie? | Doar admin-ul poate șterge orice articol |
Rolurile din aplicație
| Rol | Descriere | Cum se obține |
|---|---|---|
| Vizitator | Vede articole, nu poate crea/edita/șterge | Implicit — orice utilizator neautentificat |
| User | Poate crea articole, editează doar ale lui | Se atribuie automat la Register |
| Admin | Poate edita/șterge orice articol | Creat prin SeedData |
Vizitator nu este un rol Identity stocat în baza de date. Este starea implicită — un utilizator care nu s-a autentificat.
Notă despre ordinea pașilor: Nu se poate rula
dotnet ef migrations adddacă codul nu compilează. De aceea, toate modificările de cod (Models, DbContext, ViewModels, Views, Controllers, Program.cs, SeedData) se fac înainte de migrare.
Parte 1 — Identity: Setup și Modele
Pasul 1 — NuGet package
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
Pasul 2 — Creare ApplicationUser
Models/ApplicationUser.cs — fișier nou
using Microsoft.AspNetCore.Identity;
namespace Lab07.Models;
public class ApplicationUser : IdentityUser
{
public string FullName { get; set; } = string.Empty;
public List<Article> Articles { get; set; } = [];
}
IdentityUser oferă: Id (string/GUID), UserName, Email, PasswordHash, etc.
UserNameșiUserNameeste ceea ce se afișează în navbar (ex:"admin"),"admin@newsportal.com").
Pasul 3 — Actualizare Article.cs
În Models/Article.cs, înlocuiți referința la User cu ApplicationUser:
// Ștergeți aceste 2 linii:
// public int? UserId { get; set; }
// public User? User { get; set; }
// Adăugați în loc:
public string? AuthorId { get; set; }
public ApplicationUser? Author { get; set; }
AuthorIdestestring?(GUID), nuint?—IdentityUserfolosește GUID ca primary key.
Pasul 4 — Actualizare CreateArticleViewModel
În ViewModels/CreateArticleViewModel.cs, ștergeți câmpul UserId și lista Users:
// Ștergeți aceste linii:
// [Display(Name = "Autor")]
// public int? UserId { get; set; }
// public List<SelectListItem> Users { get; set; } = new();
Autorul nu se mai alege dintr-un dropdown — va fi setat automat din sesiunea utilizatorului curent.
EditArticleViewModelmoștenește dinCreateArticleViewModel, deci e actualizat automat.
Pasul 5 — Actualizare Views: Create și Edit
Views/Articles/Create.cshtml
Ștergeți blocul <div> cu dropdown-ul pentru UserId:
<!-- Ștergeți tot acest bloc: -->
<div class="mb-3">
<label asp-for="UserId" class="form-label"></label>
<select asp-for="UserId" class="form-select"
asp-items="Model.Users">
<option value="">-- Selectați --</option>
</select>
<span asp-validation-for="UserId" class="text-danger"></span>
</div>
Views/Articles/Edit.cshtml
Ștergeți același bloc cu dropdown-ul pentru UserId:
<!-- Ștergeți tot acest bloc: -->
<div class="mb-3">
<label asp-for="UserId" class="form-label"></label>
<select asp-for="UserId" class="form-select"
asp-items="Model.Users">
<option value="">-- Selectați --</option>
</select>
<span asp-validation-for="UserId" class="text-danger"></span>
</div>