【问题标题】:Asp.net Security: IIdentity.IsAuthenticated default implementationAsp.net 安全性:IIdentity.IsAuthenticated 默认实现
【发布时间】:2010-04-27 15:08:12
【问题描述】:

我正在编写实现 IIdentity 的自定义 Identity 类。我不需要更改默认方法 IsAuthenticated 但现在我想知道默认 IIdentity 如何确定它应该返回 true 还是 false?

我想在我正在使用的 FormsAuthenticationTicket 中找到答案,但不确定是否正确。

提前致谢,

泡菜

【问题讨论】:

    标签: asp.net security asp.net-membership


    【解决方案1】:

    在 ASP.Net 处理程序的上下文中没有“默认 IIdentity”。

    有一个 GenericIdentity 传递给 GenericPrincipal,这是 ASP.Net 处理程序的默认 User,它的行为是,如果它是用非空用户名实例化的,那么它就会通过身份验证.

    例如

    public virtual bool IsAuthenticated
    {
        get
        {
            return !this.m_name.Equals("");
        }
    }
    

    也就是说,IsAuthenticated 的确定是完全任意的,实现IIdentity 的类完全负责实现这个逻辑。

    通常,没有实例化未经身份验证的主体/身份的用例,因为这是由 asp.net 运行时自动完成的,因此使用返回 @987654329 的“哑”IsAuthenticated 实现您的自定义 IIdentity @ 在大多数情况下应该是合适的。

    此外,虽然完全实现 IPrincipalIIdentity 很简单,但您也可以简单地从 GenericPrincipalGenericIdentity 派生,从而减少需要维护的代码量。

    FormsAuthentication 的上下文中,只有在用户通过身份验证并且User 将是具有FormsIdentity 类型标识的RolePrincipal 的实例并且它的IsAuthenticated 的实现是超级复杂;-) ...

    public bool IsAuthenticated
    {
        get
        {
            return true;
        }
    }
    

    希望这有助于解决问题。

    【讨论】:

    • 从 GenericIdentity 派生是个好主意。感谢您花时间写这个答案。
    • @Pickels - 如果您计划将自定义主体/身份与 FormsAuthentication 一起使用,您可能需要调查从 RolePrincipal 和 FormsIdentity 派生的可能性,因为这些是所有内置提供程序所期望的基本类型.当然,除非您正在实施自己的提供程序堆栈,在这种情况下,所有赌注都没有了,您可以随意做。
    • 我不会使用任何我认为的提供商。我将它与 OpenID 一起使用并尝试将其存储在 MongoDB 中。我正在使用 IIdentity 进行一些测试以轻松访问我的一些用户属性(友好标识符、ObjectId、电子邮件...)
    【解决方案2】:

    我使用自定义 UserPrinciple 将有关当前用户的更多信息嵌入到我的页面中,而不是标准 GenericPrinciple 所允许的。我没有发现需要实现我自己的IIdentity,因为您可以轻松利用内置的FormsIdentity,类似于我的时尚(我不确定这是否与 Auth for .NET 的标准做法不同,它工作得很好虽然在实践中为我自己)。我确实创建了一个自定义的GuestIdentity,它返回一个硬编码的IsAuthenticated = false,也许这可以被GenericPrinciple替换我不确定它是否是抽象的。

    public class UserPrincipal : IPrincipal
    {            
    
      private readonly IIdentity _identity;
    
      public UserPrincipal()
            {
                _identity = new GuestIdentity();
    
                var guest = //my custom object
                User = guest;
            }        
        public UserPrincipal(HttpContext context)
        {
            var ident = context.User.Identity as FormsIdentity;
            string msg1 = "Context.User.Identity is null for authenticated user.";
            if (ident == null) throw new ApplicationException(msg1);
    
            _identity = ident;
            string msg2 = "Forms Identity Ticket is null";
            if (ident.Ticket == null) throw new AccessViolationException(msg2);
    
            var userData = ident.Ticket.UserData;
    
            ...
    
            User = jsonSerializer.Deserialize<User>(userJson);
        }    
        #region IPrincipal Members
        public bool IsInRole(string role)
        {
            return User.Roles.FirstOrDefault(x => x.RoleName == role) != null;
        }
    
        public IIdentity Identity
        {
            get { return _identity; }
        }
        #endregion
    }
    

    除了随机之外,您可以在表单身份验证票证中缓存数据,如扩展的 UserData,如果您遵循这种类型的想法,但请确保您有适当的逻辑,可以正确过期旧数据,因为它存储在客户端计算机上。

    【讨论】:

    • 如果我理解正确,您将 userData 存储为 Json。在我的课堂上使用它也是一个好主意。
    • 我曾考虑在此处从我的代码中删减更多内容,但我意识到其他人考虑这一点可能很有用。在某些时候,我可能会进一步分层我的答案并将结果缓存在服务器上,并且只对过期缓存值的票证进行反序列化。
    • @Pickels - 小心 cookie 中的 JSON。您需要首先将整个 JSON 字符串 UrlEncode 为 , 和其他人破坏 cookie。好的,这已经涵盖了,现在您必须记住 4k cookie 的限制,在加密之后,整个 cookie 的可用空间约为 1.8kb,在加密之前。请小心,因为 cookie 会被默默地截断。当您无缘无故地解码 cookie 并找到您的错误时,您将在 36 小时内看到影子人。
    • @code 诗人有用的信息,UrlEncoding 很可能解释为什么当我尝试使用 BSON 时它不起作用,我的序列化对象大约 200 个字节,所以它们很轻,但我会如果我添加更多内容,请记住这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 2018-04-26
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多