核心概念与准备工作
在开始编码之前,我们需要了解几个核心概念:
- 身份验证:“你是谁?” 的过程,ASP.NET 提供了内置的身份验证机制,最常用的是 ASP.NET Identity,它是一个会员系统,负责处理用户注册、登录、密码哈希、角色管理等。
- 授权:“你能做什么?” 的过程,在用户登录成功后,你可以授权他们访问特定的页面或执行特定的操作,只有管理员才能访问
/Admin页面。 - Cookie:登录成功后,服务器会生成一个包含用户身份信息的“令牌”(通常是加密的字符串),并将其存储在用户的浏览器中,之后,用户每次请求网站时,浏览器都会自动带上这个 Cookie,服务器通过验证 Cookie 来识别用户。
- ASP.NET Core Identity vs. ASP.NET (Framework) Identity:
- ASP.NET Core Identity:是当前的主流和推荐方案,它更现代化、更灵活、支持 EF Core,并且可以轻松地与外部登录提供商(如 Google, Facebook, 微信)集成,适用于 ASP.NET Core 项目。
- ASP.NET (Framework) Identity:是传统 ASP.NET MVC / Web Forms 中的身份验证系统,虽然功能强大,但已不再是新项目的首选,适用于 ASP.NET Framework 项目。
本指南将以 ASP.NET Core 和 ASP.NET Core Identity 为例进行讲解,因为它代表了未来的方向。
实现步骤(以 ASP.NET Core MVC 为例)
我们将创建一个简单的登录流程。
步骤 1:创建项目并安装 NuGet 包
- 使用 Visual Studio 或
dotnet new命令创建一个新的 ASP.NET Core Web 应用程序 (MVC 模板)。 - 项目模板通常会默认包含
Microsoft.AspNetCore.Identity.EntityFrameworkCore包,如果没有,请通过 NuGet 包管理器安装它。
步骤 2:配置数据库和 Identity 服务
-
创建
DbContext: 在Models文件夹下,创建一个继承自IdentityDbContext的类。IdentityDbContext已经包含了用户、角色、登录等所需的所有实体。// Models/ApplicationDbContext.cs using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace YourProjectName.Models { public class ApplicationDbContext : IdentityDbContext<IdentityUser> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } // 在这里可以添加你自己的实体,Products, Orders 等 } } -
注册服务: 在
Program.cs文件中,将ApplicationDbContext和 Identity 服务注册到依赖注入容器中。// Program.cs using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using YourProjectName.Models; var builder = WebApplication.CreateBuilder(args); // 1. 添加数据库服务 builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 2. 添加 Identity 服务 builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>(); // 添加其他服务,如 Controllers, Views 等 builder.Services.AddControllersWithViews(); var app = builder.Build(); // ... (中间件配置) app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // 3. 添加身份验证中间件 app.UseAuthentication(); // 必须在 UseAuthorization 之前 app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();- 注意:
UseAuthentication()中间件是必须的,它会负责处理 Cookie 的读取和验证。 AddDefaultIdentity是一个快捷方法,它会帮你配置好大部分默认设置。SignIn.RequireConfirmedAccount = true表示需要用户验证邮箱后才能登录,你可以先设为false。
- 注意:
-
配置数据库连接字符串: 在
appsettings.json文件中,添加一个 SQL Server 连接字符串,你需要先在本地 SQL Server 中创建一个数据库。{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-YourProjectName-xxxxxxxxxxxx;Trusted_Connection=True;MultipleActiveResultSets=true" }, // ... 其他配置 }(使用 LocalDB 是最简单的方式,它会自动在文件系统中创建一个数据库文件)
步骤 3:应用数据库迁移
Identity 使用 Entity Framework 的 Code First 功能,你需要创建并应用一个迁移来生成存储用户信息的数据库表。
-
打开 程序包管理器控制台 (Package Manager Console)。
-
运行以下命令:
Add-Migration InitialCreate Update-Database
Add-Migration会根据你的DbContext创建一个迁移脚本。Update-Database会执行这个脚本,在数据库中创建AspNetUsers,AspNetRoles等表。
步骤 4:创建登录相关的 UI
-
注册: 默认的 MVC 模板已经为你生成了
AccountController、Register、Login、Logout等相关的 Action 和 View。- 注册页面:
/Identity/Account/Register - 登录页面:
/Identity/Account/Login - 登出页面:
/Identity/Account/Logout
你可以直接访问这些 URL 来测试注册和登录功能,它们已经包含了基本的表单和样式。
- 注册页面:
-
自定义登录页面(可选): 如果你想使用自己的登录页面而不是默认的,可以这样做:
- 在
Views/Account文件夹下创建一个Login.cshtml文件。 - 在
AccountController中,创建一个返回View()的LoginAction。 - 在
_Layout.cshtml中,添加一个指向你登录页面的链接。
- 在
步骤 5:在代码中检查用户登录状态
我们可以在控制器或视图中保护某些页面,只允许已登录的用户访问。
-
使用
[Authorize]特性: 这是最简单的方式,在控制器或 Action 上添加此特性。using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace YourProjectName.Controllers { [Authorize] // 整个控制器都需要登录才能访问 public class DashboardController : Controller { public IActionResult Index() { // 只有登录用户才能看到这个页面 return View(); } [AllowAnonymous] // 允许匿名用户访问这个特定的 Action public IActionResult PublicInfo() { return View(); } } } -
在代码中检查: 你也可以在 Action 内部手动检查。
public class ProfileController : Controller { public IActionResult Index() { if (User.Identity.IsAuthenticated) { // 用户已登录,可以获取用户信息 var userName = User.Identity.Name; // ... 其他逻辑 return View(); } else { // 用户未登录,可以重定向到登录页面 return RedirectToAction("Login", "Account"); } } } -
获取当前用户信息: 通过依赖注入获取
UserManager或SignInManager来操作用户。public class ProfileController : Controller { private readonly UserManager<IdentityUser> _userManager; // 通过构造函数注入 UserManager public ProfileController(UserManager<IdentityUser> userManager) { _userManager = userManager; } public async Task<IActionResult> Index() { var user = await _userManager.GetUserAsync(User); if (user == null) { return NotFound(); } // 可以获取更多用户信息,如 Email, PhoneNumber 等 var email = await _userManager.GetEmailAsync(user); // ... 将数据传递给 View return View(); } }
安全最佳实践
实现登录功能,安全是重中之重。
-
绝不存储明文密码: ASP.NET Identity 会自动使用 BCrypt 或 PBKDF2 等强哈希算法对密码进行加盐哈希存储,你永远不要自己实现密码加密逻辑,直接使用 Identity 提供的
CreateAsync方法即可。 -
使用 HTTPS: 在
Program.cs中,强制使用 HTTPS,这可以防止登录凭据在网络传输中被窃听。app.UseHttpsRedirection();
-
防止暴力破解: 默认情况下,Identity 内置了登录失败次数限制和锁定机制,你可以在
Program.cs中配置它。builder.Services.AddIdentity<IdentityUser, IdentityRole>(options => { // 密码设置 options.Password.RequireDigit = true; options.Password.RequireLowercase = true; options.Password.RequireNonAlphanumeric = true; options.Password.RequireUppercase = true; options.Password.RequiredLength = 8; options.Password.RequiredUniqueChars = 1; // 登录锁定设置 options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5); options.Lockout.MaxFailedAccessAttempts = 5; options.Lockout.AllowedForNewUsers = true; }) .AddEntityFrameworkStores<ApplicationDbContext>(); -
防止跨站请求伪造: 默认情况下,ASP.NET Core MVC 会为表单自动生成并验证防伪令牌,你不需要做太多事情,只需确保在表单中使用
@Html.AntiForgeryToken()。<form asp-action="Login" asp-controller="Account"> @Html.AntiForgeryToken() <!-- 重要! --> <div> <label>用户名:</label> <input type="text" name="Input.Username" /> </div> <div> <label>密码:</label> <input type="password" name="Input.Password" /> </div> <button type="submit">登录</button> </form> -
设置安全的 Cookie: 在
Program.cs中配置 Cookie 的安全属性。builder.Services.ConfigureApplicationCookie(options => { options.Cookie.HttpOnly = true; // 防止 XSS 攻击 options.ExpireTimeSpan = TimeSpan.FromMinutes(30); // Cookie 过期时间 options.SlidingExpiration = true; // 滑动过期,每次访问都会重置计时器 options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 只在 HTTPS 下发送 });
总结与新技术
| 特性 | ASP.NET Core Identity (推荐) | ASP.NET Framework Identity (旧版) |
|---|---|---|
| 技术栈 | EF Core, .NET Core | EF6, .NET Framework |
| 数据库 | EF Core 支持 (SQL Server, SQLite, PostgreSQL, MySQL 等) | EF6 支持 |
| 灵活性 | 极高,支持无 SQL、外部登录、自定义存储 | 较高,但扩展不如 Core 方便 |
| OAuth/OpenID | 原生支持,易于集成 | 需要额外配置或使用第三方库 |
| 社区与未来 | 活跃,是未来的方向 | 维护中,不再推荐新项目使用 |
对于新项目,请毫不犹豫地选择 ASP.NET Core 和 ASP.NET Core Identity。
通过以上步骤,你已经掌握了在 ASP.NET 网站中实现一个安全、可靠的用户登录系统的核心方法,从配置、数据库迁移、UI 创建到安全实践,每一步都至关重要,希望这个详细的指南能帮助你顺利完成开发!
