C# (.NET) 中的授权与身份验证:完整指南
Web 应用程序的安全性是现代开发的基石。在 C# (.NET) 生态系统中,内置的身份验证和授权机制使您能够灵活可靠地保护您的应用程序。在本文中,我们将分析使用 Identity、JWT 和角色模型的关键概念、工具和代码示例。
1. 基本概念
在进入代码之前,有必要区分两个术语:
- 身份验证 — 验证用户身份的过程(您是谁?)。通常通过登录名/密码、令牌或外部提供商完成。
- 授权 — 确定访问权限的过程(您可以做什么?)。通过角色、策略或声明实现。
2. ASP.NET Core Identity — 内置解决方案
Microsoft.AspNetCore.Identity 是一个完整的用户管理系统,包括注册、登录、密码重置、双因素身份验证等。它与 Entity Framework Core 配合使用,并支持任何数据存储。
安装:
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCoredotnet add package Microsoft.EntityFrameworkCore.SqlServer用户注册示例(Account 控制器):
public class AccountController : Controller{ private readonly UserManager<IdentityUser> _userManager; private readonly SignInManager<IdentityUser> _signInManager;
public AccountController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager) { _userManager = userManager; _signInManager = signInManager; }
[HttpPost] public async Task<IActionResult> Register(RegisterViewModel model) { if (ModelState.IsValid) { var user = new IdentityUser { UserName = model.Email, Email = model.Email }; var result = await _userManager.CreateAsync(user, model.Password); if (result.Succeeded) { await _signInManager.SignInAsync(user, isPersistent: false); return RedirectToAction("Index", "Home"); } foreach (var error in result.Errors) ModelState.AddModelError(string.Empty, error.Description); } return View(model); }}3. JWT(JSON Web 令牌)— 无状态身份验证
对于现代 SPA(React、Angular)或移动应用程序,通常使用 JWT。令牌由服务器签名,并包含关于用户的声明。服务器不存储会话,从而简化了扩展。
在 Program.cs 中的配置:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidateAudience = true, ValidAudience = builder.Configuration["Jwt:Audience"], ValidateLifetime = true, IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; });生成令牌:
public string GenerateToken(IdentityUser user){ var claims = new[] { new Claim(ClaimTypes.NameIdentifier, user.Id), new Claim(ClaimTypes.Email, user.Email), new Claim(ClaimTypes.Role, "User") };
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
va