资讯动态

ASP.NET Core 安全实践指南:Identity 认证与 Data Protection 数据保护实战(基于 practical-aspnetcore 仓库)

发布时间:2026/10/16 2:11:58 来源:尧图企业网站定制
示例工程【免费下载链接】practical-aspnetcorePractical samples of ASP.NET Core 11, 10, 9, 8.0, 7.0, 6.0, 5.0, 3.1, 2.2, and 2.1,projects you can use. Readme contains explanations on all projects.项目地址https://gitcode.com/gh_mirrors/pr/practical-aspnetcore点击查看免费下载本文基于 practical-aspnetcore 仓库的 Security 目录系统讲解 ASP.NET Core 中两大核心安全能力基于Identity Core EF Core SQLite的用户认证体系注册、登录、登出、受限访问以及Data Protection 数据保护栈的六种密钥存储/加密方案默认设置、Azure Blob、Azure Key Vault、EF Core、Redis、自定义 XML 加密器。读完本文你将掌握如何在真实项目中注册 Identity、配置密码策略、保护受限路由并根据部署环境为 Data Protection 选择正确的密钥持久化与加密方案。仓库 Security 部分全景仓库的 projects/security/README.md 是整个安全主题的入口其下包含7 个可运行示例目录主题示例数authentication-with-identityIdentity Core EF Core SQLite 基础认证1dataprotectionData Protection 密钥存储与加密6其中 Data Protection 部分又细分为六个独立示例覆盖了从零配置开箱即用到密钥托管到 Azure/Redis/数据库的完整演进路径本文后续会逐一展开。第一部分基于 Identity Core 的用户认证实战项目定位与核心能力authentication-with-identity 是一个展示 Identity Core 基础认证流程的独立可运行示例其 README 明确列出了它提供的四项功能注册用户Register a user登录Sign in登出Sign out访问仅限已认证用户查看的页面Access to a page restricted to the authenticated users示例选择 SQLite 作为数据库是因为 SQLite 以 DLL 形式随项目分发可以让示例开箱即跑、无需额外安装数据库服务同时 Identity 支持大量其他数据库提供程序生产环境可平滑切换到 SQL Server、PostgreSQL、MySQL 等。项目结构解析从源码结构看该项目是一个典型的 MVC 三层结构Controllers/AccountController认证相关动作、HomeController公开首页、RestrictedAreaController受限区域Data/ApplicationDbContext.csEF Core 数据库上下文Services/IEmailSender与EmailSender邮件发送占位实现ViewModels/登录/注册/受限页面的视图模型Views/Account、Home、RestrictedArea、Shared 对应的 Razor 视图。项目目标框架为net10.0见 authentication-with-identity.csproj依赖以下 NuGet 包PackageReference IncludeMicrosoft.AspNetCore.Identity.EntityFrameworkCore Version10.0.11 / PackageReference IncludeMicrosoft.EntityFrameworkCore.Sqlite Version10.0.11 / PackageReference IncludeMicrosoft.EntityFrameworkCore.Design Version10.0.11 /数据库上下文IdentityDbContextIdentity 的默认用户/角色模型IdentityUser、IdentityRole需要落库示例通过 ApplicationDbContext.cs 继承IdentityDbContext完成public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptionsApplicationDbContext options) : base(options) { } }IdentityDbContext内置了用户、角色、声明、登录信息等全部 Identity 所需实体集无需手动声明任何DbSet。服务注册与密码策略配置核心配置集中在 Program.cs 的Startup类中分三个层次完成1. 数据库服务SQLiteservices.AddDbContextApplicationDbContext(options options.UseSqlite(Data Sourceidentity_db.db));连接串Data Sourceidentity_db.db会在应用目录生成 SQLite 数据库文件。2. Identity 服务用户 角色 EF 存储 默认令牌提供程序services.AddIdentityIdentityUser, IdentityRole() .AddEntityFrameworkStoresApplicationDbContext() .AddDefaultTokenProviders();3. Identity 选项示例刻意放宽的密码策略services.ConfigureIdentityOptions(options { // 最小密码策略仅要求长度 3 options.Password.RequireDigit false; options.Password.RequiredLength 3; options.Password.RequireNonAlphanumeric false; options.Password.RequireUppercase false; options.Password.RequireLowercase false; // 登录设置不强制邮箱确认 options.SignIn.RequireConfirmedEmail false; });实战提醒上述策略是为了降低示例演示门槛密码只需 3 位。生产环境务必启用更强的密码策略默认要求大小写字母、数字、特殊字符与 6 位以上长度并开启RequireConfirmedEmail、账户锁定等选项。请求管道中的认证中间件认证要真正生效还必须在管线中按顺序注册中间件顺序错误是常见的认证失效根因app.UseRouting(); app.UseAuthentication(); // 先认证 app.UseAuthorization(); // 再授权 app.UseEndpoints(endpoints { endpoints.MapDefaultControllerRoute(); });Program.Main中还通过EnsureDatabase(host)在启动时调用dbContext.Database.EnsureCreated()自动建库省去手动迁移步骤源码见 Program.cs。AccountController注册、登录、登出、邮箱确认AccountController.cs 是认证逻辑的核心通过构造函数注入UserManagerIdentityUser与SignInManagerIdentityUser。注册Register接收RegisterViewModel创建IdentityUser用户名与邮箱同值后调用userManager.CreateAsync(user, model.Password)成功后生成邮箱确认令牌并发送确认链接随后直接调用signInManager.SignInAsync(user, isPersistent: false)完成自动登录并跳转首页。登录Login调用signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false)失败时通过ModelState.AddModelError(string.Empty, Invalid login attempt.)返回通用错误信息避免泄露用户不存在等枚举攻击信息。登出LogoutsignInManager.SignOutAsync()后重定向首页。邮箱确认ConfirmEmail校验userId与code参数后依次调用FindByIdAsync与ConfirmEmailAsync确认成功渲染ConfirmEmail视图。注意AccountController类级别标有[Authorize]而Register、Login、ConfirmEmail动作用[AllowAnonymous]放行——这是一种默认安全、按需开放的经典写法。受限区域Authorization 的最小示例RestrictedAreaController.cs 只在类级别标注[Authorize]未登录访问会被中间件拦截并跳转登录页。Index动作通过userManager.GetUserAsync(User)读取当前登录用户并组装出用户名、邮箱、手机号与邮箱确认状态的IndexViewModel渲染到 Views/RestrictedArea/Index.cshtml 展示个人资料页。视图模型与表单验证RegisterViewModel.csEmail[Required][EmailAddress]、Password[Required][DataType(DataType.Password)]LoginViewModel.cs在注册模型基础上增加RememberMe布尔选项。注册/登录视图Register.cshtml、Login.cshtml使用 Tag Helperasp-for、asp-validation-for、asp-validation-summary实现服务端验证消息的自动渲染POST 动作同时标注[ValidateAntiForgeryToken]防跨站请求伪造。导航与登录状态展示_LoginPartial.cshtml 通过inject SignInManagerIdentityUser与inject UserManagerIdentityUser在视图中直接访问认证服务用SignInManager.IsSignedIn(User)分支渲染已登录显示问候语Hello User.Identity.Name!、Home/受限区域导航与 Logout 表单未登录显示 Register、Login 链接受限区域链接同样可见但访问会被拦截。该分部视图被 _Layout.cshtml 以partial name_LoginPartial /引入到全局布局中。运行示例在 authentication-with-identity 目录执行dotnet restore dotnet run启动后访问首页依次体验注册 → 自动登录 → 访问受限区域 → 登出 → 重新登录的完整闭环。第二部分Data Protection 数据保护栈六种密钥方案为什么需要 Data ProtectionASP.NET Core 的 Data Protection 栈用于对需持久化或传输的敏感数据如认证 Cookie、防伪令牌、临时数据进行加密与签名。它的核心是密钥管理密钥必须以某种方式持久化并在多实例部署时保持一致否则不同实例间加密的数据无法互相解密。仓库 dataprotection/README.md 给出了六种从简到繁的方案下面逐一实战解析。方案一默认设置零配置开箱即用default-settings 展示 Data Protection 的最简用法——只需一行注册builder.Services.AddDataProtection();对应 Program.cs 中的完整最小化宿主代码。默认行为密钥默认持久化到本机用户配置文件目录%LOCALAPPDATA%\ASP.NET\DataProtection-Keys密钥环自动按 90 天周期轮换从仓库中 custom-encryptor 的示例密钥文件 可以看到真实的密钥 XML 结构包含creationDate、activationDate、expirationDate、AES_256_CBC加密算法与HMACSHA256校验算法等元数据。加密/解密使用方式见 Pages/Index.cshtml.cs// 通过 IDataProtectionProvider 创建用途化的 protector _protector dataProtectionProvider.CreateProtector(DP.DefaultSettings.V1); // 加密 EncryptedString _protector.Protect(StringToEncrypt); // 解密 DeCryptedString _protector.Unprotect(EncryptedString);页面提交后同时展示密文与明文直观验证加解密闭环界面见 assets/main-page.png。关键概念CreateProtector(DP.DefaultSettings.V1)中的用途字符串purpose是 Data Protection 的隔离机制——不同用途创建的 protector 互相无法解密对方的数据防止密文被重放到其他场景。方案二密钥持久化到 Azure Blob 存储azure-storage-blob-key-store 解决多实例共享密钥问题把密钥环 XML 放入 Azure Blob所有实例读取同一份密钥。appsettings 配置见 appsettings.json仓库默认使用UseDevelopmentStoragetrue即 Azurite 本地模拟器DataProtection: { StorageConnectionString: UseDevelopmentStoragetrue, ContainerName: container-dp-keys, BlobName: dpkeys.xml }注册代码见 Startup.csvar storageConnectionString Configuration[DataProtection:StorageConnectionString]; var containerName Configuration[DataProtection:ContainerName]; var blobName Configuration[DataProtection:BlobName]; services.AddDataProtection() .PersistKeysToAzureBlobStorage(storageConnectionString, containerName, blobName);三个配置项的含义StorageConnectionString为存储账号连接串、ContainerName为容器名、BlobName为密钥 XML 文件名默认建议dpkeys.xml。方案三Azure Key Vault 加密 Blob 存储密钥的密钥azure-keyvault-storage-blob-key-store 是方案二的增强密钥环虽然放在 Blob 里但其主密钥master key本身由 Azure Key Vault 加密实现静态密钥加密。appsettings 配置见 appsettings.jsonDataProtection: { StorageConnectionString: UseDevelopmentStoragetrue, ContainerName: container-dp-keys, BlobName: dpkeys.xml, KeyId: https://your key vault name.vault.azure.net/keys/your key name/your key version }KeyId必须是完整的 Key Vault 密钥 URI含密钥版本。注册代码见 Startup.csvar keyId Configuration[DataProtection:KeyId]; services.AddDataProtection() // 密钥加密使用 Azure Key Vault .ProtectKeysWithAzureKeyVault( new Uri(keyId), new ChainedTokenCredential( new ManagedIdentityCredential(), new AzureCliCredential())) // 密钥持久化使用 Azure Blob Storage .PersistKeysToAzureBlobStorage(storageConnectionString, containerName, blobName);注意凭据链ChainedTokenCredential优先尝试 Azure 托管身份生产环境失败则回退到 Azure CLI 登录本地开发实现了开发/生产同代码的认证切换。方案四密钥存储到关系数据库EF Coreef-key-store 把密钥环存进关系数据库适合已有数据库基础设施、希望密钥与业务数据同库管理的团队。示例目标数据库为 SQL Server。关键步骤 1引入包与自定义 DbContext见 DataProtectionKeyContext.cs// 包Microsoft.AspNetCore.DataProtection.EntityFrameworkCore class DataProtectionKeyContext : DbContext, IDataProtectionKeyContext { public DataProtectionKeyContext(DbContextOptionsDataProtectionKeyContext options) : base(options) { } public DbSetDataProtectionKey DataProtectionKeys { get; set; } }关键步骤 2创建并应用 EF 迁移README 给出的命令dotnet ef migrations add AddDataProtectionKeys --context DataProtectionKeyContext dotnet ef database update --context DataProtectionKeyContext仓库已预置迁移产物 20210610013150_AddDataProtectionKeys.cs从中可以看到生成的DataProtectionKeys表结构Id自增主键、FriendlyName、Xml密钥 XML 内容三个字段。关键步骤 3注册 DbContext 与密钥持久化见 Startup.csvar storageConnectionString Configuration[DataProtection:DefaultConnection]; services.AddDbContextDataProtectionKeyContext(options options.UseSqlServer(storageConnectionString)); services.AddDataProtection() .PersistKeysToDbContextDataProtectionKeyContext();连接串在 appsettings 的DataProtection:DefaultConnection节点下配置。方案五密钥存储到 Redisredis-key-store 适合已使用 Redis 的分布式架构把密钥环作为 Redis 字符串键保存多实例共享且天然支持高可用。appsettings 配置见 appsettings.json仓库默认本地localhost:6379无密码DataProtection: { RedisServer: localhost:6379, RedisPassword: , RedisKey: dp-keys }注册代码见 Program.cs该示例采用 WebApplication 最小宿主var redisServer configuration[DataProtection:RedisServer]; var redisPassword configuration[DataProtection:RedisPassword]; var redisKey configuration[DataProtection:RedisKey]; var redis ConnectionMultiplexer.Connect(${redisServer},password{redisPassword}); builder.Services.AddDataProtection() .PersistKeysToStackExchangeRedis(redis, redisKey);RedisServer为 Redis 地址与端口RedisPassword为密码本地无密码时留空RedisKey为密钥环在 Redis 中的键名默认建议dp-keys。方案六自定义 XML 加密器custom-encryptor 展示如何通过实现IXmlEncryptor/IXmlDecryptor接口完全接管密钥 XML 的加密逻辑用于对接公司内部加密体系或国密等特殊算法。1. 加密器实现CustomXmlEncryptor.csEncrypt接收明文密钥 XML返回EncryptedXmlInfo新 XML 元素 对应的解密器类型。示例中为演示自定义机制故意不真正加密仅把明文包一层unencryptedKey标记public EncryptedXmlInfo Encrypt(XElement plaintextElement) { var newElement new XElement(unencryptedKey, new XComment( This key is not encrypted. ), new XElement(plaintextElement)); return new EncryptedXmlInfo(newElement, typeof(CustomXmlDecryptor)); }2. 解密器实现CustomXmlDecryptor.csDecrypt从包装元素中取出原始密钥 XMLpublic XElement Decrypt(XElement encryptedElement) { return new XElement(encryptedElement.Elements().Single()); }3. 扩展方法接入配置系统DependencyInjection.cs通过注册IConfigureOptionsKeyManagementOptions把自定义加密器挂到KeyManagementOptions.XmlEncryptor上public static IDataProtectionBuilder UseXmlEncryptor( this IDataProtectionBuilder builder, FuncIServiceProvider, IXmlEncryptor factory) { builder.Services.AddSingletonIConfigureOptionsKeyManagementOptions(serviceProvider { var instance factory(serviceProvider); return new ConfigureOptionsKeyManagementOptions(options { options.XmlEncryptor instance; }); }); return builder; }4. 组合使用见 Program.cs密钥持久化到本地temp-keys目录 自定义加密器var keysFolder Path.Combine(Directory.GetCurrentDirectory(), temp-keys); builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo(keysFolder)) .UseXmlEncryptor(s new CustomXmlEncryptor(s));仓库中预置了一个真实生成的密钥文件 key-7c2fc905-2a4b-4da4-b168-c0764b406eff.xml其encryptedSecret节点明确标注decryptorTypeCustomEncryptor.Services.CustomXmlDecryptor, ...可以直观看到自定义加密器如何被写进密钥环的 XML 序列化结果。README 原注本演示把密钥存放在磁盘临时目录不适用于生产环境。生产场景应至少使用 DPAPI/证书加密密钥或接入 Key Vault 等托管加密服务。六种方案的选择指南方案密钥存储位置密钥加密适用场景默认设置本机用户目录本机 DPAPI单实例开发/演示Azure BlobAzure Blob 存储无明文 XML多实例共享密钥环Key Vault BlobAzure Blob 存储Azure Key Vault多实例 静态加密合规要求EF Core关系数据库无已有数据库基础设施的团队RedisRedis无已用 Redis 的分布式架构自定义加密器任意示例为本地目录自定义算法对接内部/国密加密体系小结通过本仓库 Security 部分的 7 个示例可以完整掌握 ASP.NET Core 安全体系的两个核心面认证授权Identity Core 的注册/登录/登出/受限访问完整闭环含密码策略、反伪造令牌、[Authorize]声明式授权与数据保护密钥环的持久化与加密的六种生产级方案。建议按默认设置跑通 → 换存储提供程序 → 加密钥加密 → 接自定义加密器的顺序逐个运行示例并在真实项目中优先选择集中式密钥存储 托管密钥加密的组合方案。延伸阅读仓库安全主题入口projects/security/README.mdIdentity 认证示例完整源码authentication-with-identityData Protection 示例目录dataprotection仓库总览README.md 与 STRUCTURE.md赞分享示例工程【免费下载链接】practical-aspnetcorePractical samples of ASP.NET Core 11, 10, 9, 8.0, 7.0, 6.0, 5.0, 3.1, 2.2, and 2.1,projects you can use. Readme contains explanations on all projects.项目地址https://gitcode.com/gh_mirrors/pr/practical-aspnetcore点击查看免费下载相关推荐practical-aspnetcore 实战在 Redis 中持久化 ASP.NET Core 数据保护密钥Data Protection Redis Key Storepractical aspnetcore 实战在 Redis 中持久化 ASP.NET Core 数据保护密钥Data Protection Redis K示例工程ASP.NET Core 简化认证实战JWT、Cookie、混合方案与 Identity APIpractical-aspnetcore 全示例解析ASP.NET Core 简化认证实战JWT、Cookie、混合方案与 Identity APIpractical aspnetcore 全示例解析 本文示例工程基于 JWT 认证与令牌刷新保护 REST API —— practical-aspnetcore Pathway 1 实战指南Exercise 6基于 JWT 认证与令牌刷新保护 REST API —— practical aspnetcore Pathway 1 实战指南Exercise 6 本文是示例工程上一篇D2RML终极指南5分钟掌握暗黑2重制版多开神器下一篇Ryujinx模拟器深度解析如何在PC上免费畅玩Switch游戏的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑