基于数据库存储的Data Protection密钥加密.Net Core与.Net Framework 4.x认证Cookie
这个跨框架共享认证Cookie的场景我之前帮不少开发者踩过坑,核心就是让.NET Framework和.NET Core的DataProtection系统完全对齐,同时用数据库作为密钥的统一存储源,这样多台服务器都能共享密钥。下面一步步来实现:
实现步骤详解
1. 准备数据库存储密钥
首先需要在数据库中创建存储Data Protection密钥的表,以SQL Server为例,执行以下SQL脚本:
CREATE TABLE DataProtectionKeys ( Id NVARCHAR(450) PRIMARY KEY, Xml NVARCHAR(MAX) NOT NULL, CreationDate DATETIME2 NOT NULL );
这个表结构是Data Protection框架默认要求的:Id是密钥的唯一标识,Xml存储密钥的序列化内容,CreationDate记录密钥创建时间。
2. 配置.NET Core 2.0应用
2.1 安装必要的NuGet包
在你的.NET Core 2.0项目中安装以下包:
Install-Package Microsoft.AspNetCore.DataProtection.EntityFrameworkCore Install-Package Microsoft.EntityFrameworkCore.SqlServer
2.2 创建Data Protection DbContext
创建一个继承自DbContext的类,用于操作密钥表:
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; public class DataProtectionKeysContext : DbContext, IDataProtectionKeyContext { public DataProtectionKeysContext(DbContextOptions<DataProtectionKeysContext> options) : base(options) { } // 对应数据库中的DataProtectionKeys表 public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } }
2.3 配置Data Protection和Cookie认证
在Startup.cs的ConfigureServices方法中添加以下配置:
public void ConfigureServices(IServiceCollection services) { // 配置Data Protection使用数据库存储密钥 services.AddDbContext<DataProtectionKeysContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DataProtectionKeys"))); services.AddDataProtection() // 设置统一的应用名称,两个应用必须完全一致 .SetApplicationName("SharedCookieApp") // 配置使用数据库存储密钥 .PersistKeysToDbContext<DataProtectionKeysContext>() // 指定加密算法,确保和.NET Framework端一致 .UseCryptographicAlgorithms(new AuthenticatedEncryptionSettings { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm = ValidationAlgorithm.HMACSHA256 }); // 配置Cookie认证,和.NET Framework端共享Cookie services.AddAuthentication("SharedCookie") .AddCookie("SharedCookie", options => { options.Cookie.Name = ".AspNet.SharedCookie"; // 设置Cookie的域名,如果应用部署在同域名下的不同子域名,比如*.example.com options.Cookie.Domain = ".example.com"; options.Cookie.Path = "/"; options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 生产环境建议启用HTTPS }); // 其他服务配置... }
别忘了在Configure方法中启用认证中间件:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // 其他中间件... app.UseAuthentication(); // 其他中间件... }
3. 配置.NET Framework 4.x应用
3.1 安装必要的NuGet包
在你的.NET Framework 4.x项目中安装以下包:
Install-Package Microsoft.AspNet.DataProtection.EntityFramework Install-Package EntityFramework Install-Package Microsoft.AspNet.DataProtection.SystemWeb
3.2 创建Data Protection DbContext(EF6版本)
因为.NET Framework用的是Entity Framework 6,所以DbContext需要继承自EF6的DbContext:
using Microsoft.AspNet.DataProtection.EntityFramework; using System.Data.Entity; public class DataProtectionKeysContext : DbContext, IDataProtectionKeyContext { public DataProtectionKeysContext() : base("Name=DataProtectionKeys") { } // 对应web.config中的连接字符串名称 public IDbSet<DataProtectionKey> DataProtectionKeys { get; set; } }
3.3 配置Data Protection和Cookie认证
如果你的应用使用传统Forms认证,在Global.asax的Application_Start方法中添加以下配置:
using Microsoft.AspNet.DataProtection; using System.Web.Security; protected void Application_Start() { // 配置Data Protection var dataProtectionProvider = DataProtectionProvider.Create() .PersistKeysToDbContext<DataProtectionKeysContext>() .SetApplicationName("SharedCookieApp") // 和Core应用名称完全一致 .UseCryptographicAlgorithms(new AuthenticatedEncryptionSettings { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm = ValidationAlgorithm.HMACSHA256 }); // 配置FormsAuthentication使用Data Protection加密Cookie FormsAuthentication.EnableFormsAuthentication(new FormsAuthenticationOptions { CookieName = ".AspNet.SharedCookie", CookieDomain = ".example.com", // 和Core端一致 CookiePath = "/", HttpOnly = true, Secure = true, // 生产环境建议启用 DataProtectionProvider = dataProtectionProvider }); // 其他初始化代码... }
如果是使用OWIN的Cookie认证(比如ASP.NET MVC 5+),则在OWIN Startup类中配置:
using Microsoft.AspNet.DataProtection; using Microsoft.Owin.Security.Cookies; using Owin; public class Startup { public void Configuration(IAppBuilder app) { var dataProtectionProvider = DataProtectionProvider.Create("SharedCookieApp") .PersistKeysToDbContext<DataProtectionKeysContext>() .UseCryptographicAlgorithms(new AuthenticatedEncryptionSettings { EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC, ValidationAlgorithm = ValidationAlgorithm.HMACSHA256 }); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = "SharedCookie", CookieName = ".AspNet.SharedCookie", CookieDomain = ".example.com", CookiePath = "/", HttpOnly = true, Secure = CookieSecureOption.Always, DataProtectionProvider = dataProtectionProvider }); } }
同时在web.config中配置正确的数据库连接字符串:
<connectionStrings> <add name="DataProtectionKeys" connectionString="Server=your-server;Database=your-db;User Id=your-user;Password=your-password;" providerName="System.Data.SqlClient" /> </connectionStrings>
4. 关键注意事项
- 应用名称必须完全一致:两个应用的
SetApplicationName参数要一模一样,Data Protection框架靠这个识别"同一个应用",才能复用密钥。 - 数据库权限要到位:所有Web服务器的应用池账户必须拥有
DataProtectionKeys表的读写权限,确保能正常存取密钥。 - Cookie配置完全统一:Cookie的名称、域名、路径、HttpOnly、Secure等属性必须完全相同,否则浏览器不会在两个应用间共享Cookie。
- 加密算法严格对齐:两个应用必须使用相同的加密算法组合,不然无法解密对方生成的Cookie内容。
- 多服务器无需文件共享:密钥存在数据库后,所有服务器都会从同一个数据源读取密钥,不用再配置复杂的共享文件系统。
内容的提问来源于stack exchange,提问作者lsafford
相关产品推荐
相关产品推荐

