我一直在使用基于表单和基于声明的身份验证的网站(使用ASP.NET C#)。我想覆盖ClaimsIdentity类,以便我可以实现自定义IsAuthenticated方法,并为声明身份验证特定的身份添加更多属性。
我正在实现一个自定义的WSFederationAuthentionModule,但是我试图找出我应该覆盖哪个模块(具体是什么方法),这样我就可以设置我的自定义身份/主体而不是默认的ClaimsPrincipal?
到目前为止,我已经查看了SessionAuthenticationModule和ClaimsPrincipalHTTPModule,但我无法弄清楚设置主体的步骤/覆盖它的最佳方法。
由于
增加: 由于我对此有点新意,让我确定这是正确的:设置标识的方法是设置一个自定义主体,设置为使用该标识:
System.Threading.Thread.CurrentPrincipal = customClaimsPrincipal;
或者,如果不需要自定义主体,则可以使用ClaimsIdentityCollection构造ClaimPrincipal类。
答案 0 :(得分:3)
有几个地方可以做到这一点,但是如果你使用的是SessionAuthenticationModule
,那么有些过程没有很好地记录下来,这可能会使定制主要技巧变得棘手。本答案的其余部分解释了使用SessionAuthenticationModule
时处理此问题的一种可能方法。
覆盖SessionAuthenticationModule.SetPrincipalFromSessionToken
方法。
SessionAuthenticationModule将安全令牌,主体,身份和声明存储在cookie和内存缓存中,以避免在每次请求时都必须到身份提供者/令牌服务进行往返。没有记录的是缓存的存在,它是第一个检查的位置,然后是cookie,以及序列化ClaimsPrincipal
的限制。
如果您已在ClaimsAuthenticationManager.Authenticate
中设置了自定义主体并且缓存完好无损,则自缓存存储本机.NET对象后,您的自定义主体很可能已存在。如果您尚未设置自定义主体,或者未填充缓存,则将从FedAuth会话cookie中检索安全令牌。
当令牌被序列化/反序列化到cookie时,该进程使用自定义序列化,该序列化只能读取和写入IClaimsPrincipal
和IClaimsIdentity
接口的属性(或{{1 }和ClaimsPrinicpal
类 - 我不记得哪个)。不包括任何自定义主体和标识对象属性。有可能覆盖序列化,但这需要多个(3个IIRC)层次的类覆盖。
您还需要了解基础ClaimsIdentity
方法创建新的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;
}
的基类实现。
SessionAuthenticationModule.ContextSessionSecurityToken
答案 1 :(得分:1)
你是正确的,因为HttpModules是可扩展性的方法,但要确保你实现的任何逻辑都不会抑制你的应用程序的性能。在向应用程序添加太多HttpModule之后,我已经让网站在性能方面彻底疯狂了。根据您正在使用的auth模型,可能值得缓存查询结果。
您需要弄清楚在什么条件下需要使用自定义ClaimsPrincipal。直到你这样做,你才会在黑暗中刺伤。是否有您需要声明身份验证的特定网址?