You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从MVC生成的AspNetCore.Cookie中提取WebForm所需的Claims

场景目标

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

架构设计

架构设计图

MVC实现

以下代码用于生成截图中的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生成的Cookie

WebForm实现

用户在MVC站点点击“Web form”后,通过反向代理重定向并传递HTTP头,WebForm端已获取到如下Cookie:
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

  1. 确保WebForm与MVC项目使用相同的数据保护密钥环和配置,可将密钥存储在共享文件路径、云密钥保管库,或手动指定一致密钥。
  2. 在WebForm项目中引用Microsoft.AspNetCore.DataProtection相关NuGet包,通过数据保护提供者解密Cookie值。
  3. 解密后得到序列化的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:10:39