news 2026/7/19 8:21:07

ASP.NET Core身份认证实战:从Cookie到JWT

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ASP.NET Core身份认证实战:从Cookie到JWT

1. 为什么需要身份认证?

在Web开发中,身份认证(Authentication)是确认用户身份的过程,就像进入办公楼需要刷卡一样。ASP.NET Core提供了灵活的身份认证系统,可以集成多种认证方式。我最近在一个电商项目中实现了基于Cookie的身份认证,发现很多开发者对基础认证流程存在误解。

ASP.NET Core的身份认证系统基于中间件(Middleware)构建,通过认证方案(Authentication Scheme)来组织认证逻辑。最常见的三种认证方式是:

  • Cookie认证(适合传统Web应用)
  • JWT(适合API和SPA应用)
  • OAuth/OpenID Connect(适合第三方登录)

提示:选择认证方式时,要考虑应用类型(Web/API/混合)、安全需求和用户体验。例如纯API服务用JWT更合适,而需要持久会话的Web应用则更适合Cookie。

2. 搭建基础认证环境

2.1 创建ASP.NET Core项目

首先用命令行创建新项目:

dotnet new webapp -n AuthDemo cd AuthDemo

2.2 添加必要的NuGet包

对于基础认证,需要添加:

dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore dotnet add package Microsoft.EntityFrameworkCore.SqlServer

2.3 配置Startup类

Program.cs中添加认证服务:

var builder = WebApplication.CreateBuilder(args); // 添加认证服务 builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddCookie(); var app = builder.Build(); // 启用认证中间件 app.UseAuthentication(); app.UseAuthorization();

注意:UseAuthentication必须放在UseRouting之后、UseEndpoints之前,这是常见的配置错误点。

3. 实现用户登录功能

3.1 创建用户模型

添加Models/User.cs

public class User { public int Id { get; set; } public string Username { get; set; } public string Password { get; set; } // 实际项目应使用哈希存储 }

3.2 创建登录页面

Pages文件夹下添加Login.cshtml

@page @model AuthDemo.Pages.LoginModel <h2>Login</h2> <form method="post"> <div> <label asp-for="Input.Username"></label> <input asp-for="Input.Username" /> </div> <div> <label asp-for="Input.Password"></label> <input asp-for="Input.Password" type="password" /> </div> <button type="submit">Login</button> </form>

3.3 实现登录逻辑

Login.cshtml.cs中:

public class LoginModel : PageModel { [BindProperty] public InputModel Input { get; set; } public class InputModel { [Required] public string Username { get; set; } [Required] public string Password { get; set; } } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) return Page(); // 实际项目应从数据库验证 if (Input.Username == "admin" && Input.Password == "123456") { var claims = new List<Claim> { new Claim(ClaimTypes.Name, Input.Username), new Claim("CustomClaim", "ExampleValue") }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties { IsPersistent = true // 持久化Cookie }); return RedirectToPage("/Index"); } ModelState.AddModelError(string.Empty, "Invalid login attempt."); return Page(); } }

4. 保护页面和授权

4.1 添加授权属性

在需要保护的页面或控制器上添加:

[Authorize] public class SecureModel : PageModel { public void OnGet() { } }

4.2 获取用户信息

在受保护的页面中可以通过以下方式获取用户信息:

var username = User.Identity.Name; var customClaim = User.FindFirst("CustomClaim")?.Value;

4.3 登出功能

添加登出端点:

public async Task<IActionResult> OnPostLogoutAsync() { await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return RedirectToPage("/Index"); }

5. 常见问题与解决方案

5.1 Cookie安全性配置

生产环境必须配置安全Cookie:

services.ConfigureApplicationCookie(options => { options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.SlidingExpiration = true; options.ExpireTimeSpan = TimeSpan.FromDays(30); });

5.2 认证失败处理

自定义认证失败返回:

services.ConfigureApplicationCookie(options => { options.AccessDeniedPath = "/AccessDenied"; options.LoginPath = "/Login"; });

5.3 多角色授权

添加角色声明:

var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, "Admin") };

然后使用角色授权:

[Authorize(Roles = "Admin")] public class AdminModel : PageModel { // ... }

6. 进阶:集成Entity Framework Core

6.1 创建DbContext

public class AppDbContext : IdentityDbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } }

6.2 配置Identity服务

替换之前的简单认证:

builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddDefaultIdentity<IdentityUser>(options => { options.Password.RequireDigit = true; options.Password.RequiredLength = 8; }).AddEntityFrameworkStores<AppDbContext>();

6.3 使用Identity登录

修改登录逻辑:

var result = await _signInManager.PasswordSignInAsync( Input.Username, Input.Password, Input.RememberMe, lockoutOnFailure: false); if (result.Succeeded) { return LocalRedirect(returnUrl); }

7. 性能优化技巧

7.1 会话存储优化

将会话数据存储在分布式缓存中:

builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(20); options.Cookie.HttpOnly = true; });

7.2 声明转换

减少Cookie大小:

services.AddClaimsTransformation(principal => { var claims = principal.Claims.ToList(); // 转换或过滤声明 return Task.FromResult(new ClaimsPrincipal(new ClaimsIdentity(claims))); });

7.3 认证方案缓存

对于高并发场景:

services.AddSingleton<IAuthenticationSchemeProvider, CachingSchemeProvider>();

8. 安全最佳实践

8.1 密码策略

强制使用强密码:

services.Configure<IdentityOptions>(options => { options.Password.RequireDigit = true; options.Password.RequireLowercase = true; options.Password.RequireNonAlphanumeric = true; options.Password.RequireUppercase = true; options.Password.RequiredLength = 8; });

8.2 CSRF防护

确保表单有防伪令牌:

<form method="post"> @Html.AntiForgeryToken() <!-- 表单内容 --> </form>

8.3 安全头设置

添加安全HTTP头:

app.Use(async (context, next) => { context.Response.Headers.Add("X-Content-Type-Options", "nosniff"); context.Response.Headers.Add("X-Frame-Options", "DENY"); await next(); });

9. 测试与调试

9.1 单元测试示例

测试受保护端点:

[Fact] public async Task SecurePage_RequiresAuthentication() { var client = _factory.CreateClient(); var response = await client.GetAsync("/Secure"); Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); Assert.StartsWith("http://localhost/Login", response.Headers.Location.OriginalString); }

9.2 调试认证流程

启用详细日志:

"Logging": { "LogLevel": { "Microsoft.AspNetCore.Authentication": "Debug" } }

9.3 使用Postman测试

配置Cookie测试:

  1. 先发送登录请求
  2. 从响应头获取Set-Cookie值
  3. 在后续请求中添加Cookie头

10. 实际项目经验分享

在最近的项目中,我们遇到了Cookie在子域名间共享的问题。解决方案是配置:

options.Cookie.Domain = ".example.com";

另一个常见问题是用户会话并发控制。可以通过以下方式实现:

services.Configure<SecurityStampValidatorOptions>(options => { options.ValidationInterval = TimeSpan.FromMinutes(30); });

对于高安全要求的系统,建议添加二次认证。可以使用ASP.NET Core的Authenticator库:

services.AddAuthentication() .AddGoogleAuthenticator(options => { options.SecretLength = 20; });

最后,别忘了定期审计认证日志。可以创建一个中间件来记录关键认证事件:

app.Use(async (context, next) => { if (context.Request.Path.StartsWithSegments("/login")) { var logger = context.RequestServices.GetRequiredService<ILogger<Program>>(); logger.LogInformation("Login attempt from {IP}", context.Connection.RemoteIpAddress); } await next(); });
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/19 8:20:38

WPS Office 2026免费安装指南:AI办公与安全使用全解析

还在为办公软件的选择而纠结吗&#xff1f;面对微软Office高昂的费用和复杂的激活流程&#xff0c;很多用户都在寻找一个既免费又好用的替代方案。WPS Office作为国产办公软件的佼佼者&#xff0c;不仅完全免费&#xff0c;还提供了与Microsoft Office高度兼容的体验。但网上充…

作者头像 李华
网站建设 2026/7/19 8:16:59

Unity贪吃金币游戏毕业设计:从核心玩法到性能优化的完整开发指南

1. 项目概述&#xff1a;从“贪吃蛇”到“贪吃金币”的毕业设计突围 又到了一年一度的毕业季&#xff0c;对于计算机、软件工程或数字媒体技术专业的同学来说&#xff0c;毕业设计是大学四年学习成果的集中展示。选择一个既有技术深度&#xff0c;又能完整展现个人能力&#xf…

作者头像 李华
网站建设 2026/7/19 8:14:37

Flask用户登录功能实战:安全认证与性能优化

1. Flask博客用户登录功能实战解析 在Web开发中&#xff0c;用户认证系统是任何博客项目的核心模块。作为Python轻量级框架的Flask&#xff0c;通过Flask-Login扩展可以快速实现专业的登录功能。不同于Django自带完整认证系统&#xff0c;Flask需要开发者手动集成各个组件&…

作者头像 李华
网站建设 2026/7/19 8:14:31

FPGA选型与应用全景解析:从参数到实践

1. FPGA选型与应用全景解析 在数字电路设计领域&#xff0c;FPGA&#xff08;现场可编程门阵列&#xff09;因其高度灵活性和并行处理能力&#xff0c;已成为现代电子系统的核心器件之一。作为一名长期从事FPGA开发的工程师&#xff0c;我见证了这个领域从通信基站专用设备向消…

作者头像 李华
网站建设 2026/7/19 8:12:09

研发项目管理系统任务书

一、项目概述 随着企业数字化研发体系不断完善&#xff0c;软件研发、技术迭代、产品创新类项目数量持续激增&#xff0c;研发工作具备需求迭代快、技术难度高、版本更新频繁、人员协作密集、流程管控严谨的行业特征。传统企业研发管理普遍采用线下沟通、文档零散记录、Excel进…

作者头像 李华
网站建设 2026/7/19 8:10:31

UHS-II SD卡主机控制器寄存器深度解析与驱动开发实战

1. 项目概述&#xff1a;从寄存器手册到驱动实战如果你正在开发基于AM62L这类嵌入式处理器的存储接口驱动&#xff0c;或者需要对UHS-II SD卡主机控制器进行底层调试&#xff0c;那么你大概率已经翻开了那本厚厚的《Technical Reference Manual》。手册里那些密密麻麻的寄存器位…

作者头像 李华