ASP.NET Identity 2.0 解密 Owin cookie

Posted

技术标签:

【中文标题】ASP.NET Identity 2.0 解密 Owin cookie【英文标题】:ASP.NET Identity 2.0 decrypt Owin cookie 【发布时间】:2015-08-09 10:05:59 【问题描述】:

我正在应用多租户的服务器端应用程序中工作。在这个服务器端,我有一个 Backoffice (ASP.NET MVC) 和一个 BackEnd (WCF)。

我想解密身份 cookie,以便我可以检查它是否有效并使用它在 WCF 服务中进行身份验证。

更具体地说,我真的很想知道 ASP.NET Identity API 是否提供类似以下示例的任何类型的服务(如果我使用表单身份验证,它会起作用)

FormsAuthenticationTicket formsTicket = FormsAuthentication.Decrypt(tokenValue);

提前致谢。

【问题讨论】:

请更正标题中的错字(“owin” => “own”) 没错,我的意思是欧文饼干不是我自己的饼干 好的,但是,为什么在问题的任何地方都没有创造这个词呢?标题应该是问题的摘要,因此您最好在问题中提供有关该问题的详细信息(我不知道“Owin cookie”是什么......)。但也许 asp 家伙知道这是关于什么的...... ASP.net Identity 使用 Owin,了解 asp.net identity 的人都知道,我没有在问题正文中提及它,因为一旦它出现在标题中,我认为它是无关紧要的信息 【参考方案1】:

经过大量研究,我在博客中找到了一种方法。最终算法如下所示:

      private bool BackOfficeUserAuthorized(string ticket)
      
        ticket = ticket.Replace('-', '+').Replace('_', '/');

        var padding = 3 - ((ticket.Length + 3) % 4);
        if (padding != 0)
            ticket = ticket + new string('=', padding);

        var bytes = Convert.FromBase64String(ticket);

        bytes = System.Web.Security.MachineKey.Unprotect(bytes,
            "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware",
                "ApplicationCookie", "v1");

        using (var memory = new MemoryStream(bytes))
        
            using (var compression = new GZipStream(memory,
                                                CompressionMode.Decompress))
            
                using (var reader = new BinaryReader(compression))
                
                    reader.ReadInt32();
                    string authenticationType = reader.ReadString();
                    reader.ReadString();
                    reader.ReadString();

                    int count = reader.ReadInt32();

                    var claims = new Claim[count];
                    for (int index = 0; index != count; ++index)
                    
                        string type = reader.ReadString();
                        type = type == "\0" ? ClaimTypes.Name : type;

                        string value = reader.ReadString();

                        string valueType = reader.ReadString();
                        valueType = valueType == "\0" ?
                                       "http://www.w3.org/2001/XMLSchema#string" :
                                         valueType;

                        string issuer = reader.ReadString();
                        issuer = issuer == "\0" ? "LOCAL AUTHORITY" : issuer;

                        string originalIssuer = reader.ReadString();
                        originalIssuer = originalIssuer == "\0" ?
                                                     issuer : originalIssuer;

                        claims[index] = new Claim(type, value,
                                               valueType, issuer, originalIssuer);
                    

                    var identity = new ClaimsIdentity(claims, authenticationType,
                                                  ClaimTypes.Name, ClaimTypes.Role);

                    var principal = new ClaimsPrincipal(identity);

                    return principal.Identity.IsAuthenticated;
                
            
        
    

请注意,principal 就像在发送您刚刚调用的身份验证 cookie 的一方:

HttpContext.Current.User

如果你有兴趣知道算法是如何工作的,你可以找到它here

【讨论】:

绝妙的答案,允许我在 WCF 服务中使用我现有的 OWIN 表单身份验证设置,只需注入 cookie 客户端,然后使用此服务器端允许 WCF 获取 ClaimsIdentity。拯救了这一天! 您可以避免使用new TicketSerializer().Deserialize(bytes); 解析字节数组。然后只需将身份直接传递给ClaimsPriniciple【参考方案2】:

当您将 ASP .NET 应用程序配置为使用 cookie 身份验证时,您可以为您自己的 TicketDataFormat 对象提供您自己的 IDataProtector(通常在 Startup.Auth.cs 中):

app.UseCookieAuthentication(new CookieAuthenticationOptions

    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    TicketDataFormat = new TicketDataFormat(...), // Use your own TicketDataFormat
    Provider = new CookieAuthenticationProvider
           
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
            validateInterval: TimeSpan.FromMinutes(30),
            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
    
);

如果您对两个应用程序使用相同的TicketDataFormat,您可以像这样获得AuthenticationTicket

AuthenticationTicket ticket = options.TicketDataFormat.Unprotect(cookie.Value);

【讨论】:

以上是关于ASP.NET Identity 2.0 解密 Owin cookie的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Identity 2.0 注销不起作用

在 ASP.NET Identity 2.0 中获取当前用户 ID

如何在现有数据库中实现 ASP.NET Identity 2.0?

Asp.net Identity 2.0 更新用户

迁移到 Asp.Net Identity 2.0:未在 AspNetUsers 表中创建新列

Asp.NET Core 2.0 API 控制器中的 User.Identity.Name 为空