将ASP.NET Core Identity迁移为使用SQL数据库Data Protection时遇到令牌无效与加密异常
异常根因定位
抛出的空引用(source参数为null)报错,核心触发点是DataProtection的EF Core仓库组件在查询密钥表时,没有从你指定的DbContext中获取到有效查询源。
堆栈显示报错位置在EntityFrameworkCoreXmlRepository.GetAllElements()内部调用AsNoTracking方法时,传入了null的IQueryable,本质原因是配置PersistKeysToDbContext<MyDbContext>()时,未在对应的MyDbContext中注册DataProtection依赖的实体集,导致EF Core无法构建针对密钥表的查询。
修复步骤
- 第一步:在指定的DbContext中注册DataProtection密钥实体
找到传入PersistKeysToDbContext的那个DbContext类,显式添加DataProtection所需实体的DbSet属性,需提前安装和当前.NET Core 3.1版本匹配的Microsoft.AspNetCore.DataProtection.EntityFrameworkCore包:using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; public class MyDbContext : IdentityDbContext { // 原有代码保持不变 // 添加如下属性 public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } } - 第二步:生成迁移并创建对应表
完成DbContext修改后,重新生成EF Core迁移,执行数据库更新命令,确保DataProtectionKeys表被正确创建:
注意MVC和API应用如果共用同一个数据库,只需要在其中一个项目的上下文里完成表创建即可,避免两边重复生成迁移导致结构冲突。Add-Migration AddDataProtectionKeys Update-Database - 第三步:对齐两个应用的DataProtection配置参数
仅共享数据库密钥表还不足以解决最初的“令牌无效”问题,必须保证两个应用的DataProtection配置完全一致:- 显式设置统一的应用名称:在
AddDataProtection的链式调用中补充.SetApplicationName("你的共用应用唯一标识"),MVC和API配置的名称必须完全相同。ASP.NET Core Identity生成的用户确认令牌会绑定应用名称参数,就算密钥存储位置一致,应用名称不匹配时,解密校验依然会判定令牌无效。 - 统一包版本:确保两个项目引用的
Microsoft.AspNetCore.DataProtection.EntityFrameworkCore版本和.NET Core 3.1的框架版本匹配,不要混用.NET 5/6/7对应的高版本包,避免出现接口不兼容引发的运行时异常。
- 显式设置统一的应用名称:在
- 第四步:表结构校验
如果之前手动创建过DataProtectionKeys表,需要确认表结构符合EF Core的默认映射约定:表名应为DataProtectionKeys,包含自增主键Id、类型为nvarchar(max)的Xml列,用于存储序列化的密钥XML内容,结构不匹配也会触发查询异常。
运行注意事项
- 确保MVC和API两个项目使用完全相同的数据库连接字符串,保证两边都能正常读写同一张密钥表。
- 修改配置完成后,先分别重启两个应用,让两边的DataProtection组件从数据库加载完整的密钥环,再测试注册令牌的生成和校验流程,避免在密钥初始化完成前触发加密请求。
内容的提问来源于stack exchange,提问作者CidaoPapito
相关产品推荐
相关产品推荐

