如何从MVC生成的AspNetCore.Cookie中提取WebForm所需的Claims
流程始于登录,用户认证后重定向至MVC应用,使用标准的**Sign-In实现(Cookie Scheme)**创建会话并存储于HTTP Cookie。生成Claims并在浏览器展示后,用户无需重复输入凭证即可访问WebForm站点,且WebForm需像MVC一样展示这些Claims。MVC与WebForm部署在不同服务器,通过反向代理在HTTP头中传递Claims。

以下代码用于生成截图中的Cookie:
public async Task CreateIdentityAsync() { var claims = httpContext.User.Claims; var userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(userIdentity); await httpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal); }
生成的Claims信息示例:
- http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier : Admin
- http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name : Admin
- ServerId : 4668
- UserID : AF45F-B3F...
- other-irrelevant-claim : ...
Cookie在浏览器中的存储形式:
用户在MVC站点点击“Web form”后,通过反向代理重定向并传递HTTP头,WebForm端已获取到如下Cookie:
代码如下:
public partial class SiteMaster : MasterPage { private const string NO_COOKIES_MESSAGE = "No Cookies available"; private const string ASPNET_COOKIES = ".AspNetCore.Cookies"; protected void Page_Load(object sender, EventArgs e) { var cookie = Request.Cookies.Get(ASPNET_COOKIES); var value = cookie?.Value ?? NO_COOKIES_MESSAGE; lblCookie.ForeColor = value == NO_COOKIES_MESSAGE ? Color.Red : Color.Black; lblCookie.Text = value; // <-- 在WebForm中展示Cookie var claims = GetTheClaimsFromCookies(value); // <-- 如何获取Claims??? } private IEnumerable<Claim> GetTheClaimsFromCookies(string value) { // 逻辑待实现... } }
针对基于AuthenticateAsync()的两个疑问,解答如下:
1. 是否需要解码Cookie?
是的,必须解码Cookie。AspNetCore的.AspNetCore.Cookies值是经过加密、序列化处理的,直接读取的字符串无法解析出Claims。Cookie的加密依赖应用配置中的数据保护密钥,因此WebForm项目需要和MVC项目共享相同的数据保护配置,才能完成正确解密。
2. 如何将Cookie注入回Authentication Identity?
由于WebForm是传统ASP.NET(非Core)项目,无法直接使用AspNetCore的AuthenticateAsync()方法,推荐两种处理方案:
方案一:共享数据保护配置,手动解密解析Claims
- 确保WebForm与MVC项目使用相同的数据保护密钥环和配置,可将密钥存储在共享文件路径、云密钥保管库,或手动指定一致密钥。
- 在WebForm项目中引用
Microsoft.AspNetCore.DataProtection相关NuGet包,通过数据保护提供者解密Cookie值。 - 解密后得到序列化的
AuthenticationTicket对象,反序列化即可获取ClaimsPrincipal,进而提取Claims。
示例实现GetTheClaimsFromCookies方法:
private IEnumerable<Claim> GetTheClaimsFromCookies(string cookieValue) { if (string.IsNullOrEmpty(cookieValue)) return Enumerable.Empty<Claim>(); // 配置需与MVC项目完全一致 var dataProtectionProvider = DataProtectionProvider.Create(new DirectoryInfo(@"共享密钥存储路径"), config => config.SetApplicationName("你的统一应用名称")); var protector = dataProtectionProvider.CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", "Cookies", "v2"); var ticketDataFormat = new TicketDataFormat(protector); try { var ticket = ticketDataFormat.Unprotect(cookieValue); return ticket.Principal.Claims; } catch { // 处理解密失败场景(如Cookie篡改、密钥不匹配) return Enumerable.Empty<Claim>(); } }
方案二:反向代理传递解析后的Claims(更简洁可靠)
既然已通过反向代理传递HTTP头,可在MVC端提前解析Claims,将需要的内容以自定义HTTP头形式传递给WebForm,WebForm直接读取头信息即可获取Claims,无需处理Cookie解密逻辑。
MVC端跳转前添加逻辑:
var claimsDict = User.Claims.ToDictionary(c => c.Type, c => c.Value); foreach (var claim in claimsDict) { Response.Headers.Add($"X-Claim-{claim.Key}", claim.Value); }
WebForm端Page_Load中读取Claims:
var claims = Request.Headers.AllKeys .Where(k => k.StartsWith("X-Claim-")) .Select(k => new Claim(k.Replace("X-Claim-", ""), Request.Headers[k])) .ToList();
内容的提问来源于stack exchange,提问作者Cesar Urdaneta

