首页 文章

自定义Principal / Identity设置的最佳位置在哪里?

提问于
浏览
4

我一直在使用基于表单和基于声明的身份验证的网站(使用ASP.NET C#) . 我想覆盖ClaimsIdentity类,以便我可以实现自定义IsAuthenticated方法,并为声明身份验证特定的标识添加更多属性 .

我目前正在实现一个自定义的WSFederationAuthentionModule,但是我试图弄清楚我应该覆盖哪个模块(具体是什么方法)所以我可以设置我的自定义身份/主体而不是默认的ClaimsPrincipal?

到目前为止,我已经查看了SessionAuthenticationModule和ClaimsPrincipalHTTPModule,但我无法弄清楚设置主体的步骤/覆盖它的最佳方法 .

谢谢

Addition: 由于我对此有点新意,让我确定这是正确的:设置标识的方法是设置一个自定义主体,设置为使用该标识:

System.Threading.Thread.CurrentPrincipal = customClaimsPrincipal;

或者,如果不需要自定义主体,则可以使用ClaimsIdentityCollection构造ClaimPrincipal类 .

2 回答

  • 3

    有几个地方你可以做到这一点,但如果你使用 SessionAuthenticationModule ,一些过程没有很好地记录,这可能使使用自定义主要棘手 . 本回答的其余部分解释了使用 SessionAuthenticationModule 时处理此问题的一种可能方法 .

    覆盖 SessionAuthenticationModule.SetPrincipalFromSessionToken 方法 .

    SessionAuthenticationModule将安全令牌,主体,身份和声明存储在cookie和内存缓存中,以避免在每次请求时都要到身份提供者/令牌服务进行往返 . 没有记录的是缓存的存在,它是第一个检查的位置,然后是cookie,以及序列化 ClaimsPrincipal 的限制 .

    如果您已在 ClaimsAuthenticationManager.Authenticate 中设置了自定义主体并且缓存完好无损,则自缓存存储本机.NET对象后,您的自定义主体很可能已存在 . 如果尚未设置自定义主体,或者未填充缓存,则将从FedAuth会话cookie中检索安全令牌 .

    当令牌被序列化/反序列化到cookie时,该进程使用自定义序列化,该序列化只能读取和写入 IClaimsPrincipalIClaimsIdentity 接口的属性(或者 ClaimsPrinicpalClaimsIdentity 类 - 我不记得哪个) . 不包括任何自定义主体和标识对象属性 . 有可能覆盖序列化,但这需要多个(3个IIRC)层次的类覆盖 .

    您还需要了解基本 SetPrincipalFromSessionToken 方法创建一个新的 ClaimsPrincipal 对象并在线程和上下文中设置它的事实,因此即使 sessionSecurityToken 参数包含自定义主体对象,它也会被转换回 ClaimsPrincipal 宾语 .

    这是一个示例覆盖方法:

    protected override void SetPrincipalFromSessionToken(SessionSecurityToken sessionSecurityToken)
    {
        SessionSecurityToken newToken = MyClaimsPrincipalUtility.CreateCustomClaimsPrincipalToken(sessionSecurityToken);
    
        base.SetPrincipalFromSessionToken(newToken);
    
        //the following lines need to be set after the base method call, because the base method overwrites the Principal object
        HttpContext.Current.User = newToken.ClaimsPrincipal;
        Thread.CurrentPrincipal = newToken.ClaimsPrincipal;
    }
    

    基类( SessionAuthenticationModule )实现如下所示 . 因此,有几种不同的方法可以实现覆盖和获取自定义声明主体 .

    protected virtual void SetPrincipalFromSessionToken(SessionSecurityToken sessionSecurityToken)
    {
        IClaimsPrincipal fromIdentities = ClaimsPrincipal.CreateFromIdentities(this.ValidateSessionToken(sessionSecurityToken));
    
        HttpContext.Current.User = (IPrincipal) fromIdentities;
        Thread.CurrentPrincipal = (IPrincipal) fromIdentities;
    
        //tracing code removed
    
        this.ContextSessionSecurityToken = sessionSecurityToken;
    }
    

    以防万一're wondering, here'是 SessionAuthenticationModule.ContextSessionSecurityToken 的基类实现 .

    public virtual SessionSecurityToken ContextSessionSecurityToken
    {
        get
        {
            return (SessionSecurityToken) HttpContext.Current.Items[(object) typeof (SessionSecurityToken).AssemblyQualifiedName];
        }
        internal set
        {
            HttpContext.Current.Items[(object) typeof (SessionSecurityToken).AssemblyQualifiedName] = (object) value;
        }
    }
    
  • 1

    你是正确的,因为HttpModules是可扩展性的方法,但要确保你实现的任何逻辑都不会抑制你的应用程序的性能 . 在向应用程序添加太多HttpModule之后,我已经让网站在性能方面彻底疯狂了 . 根据您使用的auth模型,可能值得缓存查询结果 .

    您需要弄清楚在什么条件下需要使用自定义ClaimsPrincipal . 直到你这样做,你才会在黑暗中刺伤 . 是否有您需要声明身份验证的特定网址?

相关问题