在VS 2012 / .NET 4.5 / ASP.NET MVC 4应用程序中,我有一个源自ClaimsIdentity
的自定义标识类型。它只是向基类添加了一些readonly属性,以便为方便起见从某些声明中读取值:
public class AppIdentity : ClaimsIdentity
{
public AppIdentity(IEnumerable<Claim> claims) : base(claims, "Custom")
public string CustomProp { get { return FindFirst("CustomClaim").Value; } }
// etc.
}
在自定义ClaimsAuthenticationManager
中,我将传入的主体转换为包含上述标识的主体,为此主体创建标记并将标记写入cookie:
var claims = new List<Claim>
{
new Claim("CustomClaim", "CustomValue"),
// etc.
};
var newPrincipal = new ClaimsPrincipal(new AppIdentity(claims));
var sessionToken = new SessionToken(newPrincipal, TimeSpan,FromHours(24));
FederatedAuthentication.SessionAuthenticationModule
.WriteSessionTokenToCookie(sessionToken);
如果我在控制器操作中获取后续请求的标识,那么......
var identity = ClaimsPrincipal.Current.Identity;
...我发现有时候identity
的运行时类型是AppIdentity
,有时它只是它的基类型ClaimsIdentity
。我的自定义声明始终显示在Claims
的{{1}}集合中。
当工作进程被回收时,身份似乎“丢失”了我期望的类型identity
。我目前只在此项目中使用IIS Express开发服务器,例如,当我在web.config中进行一些小的更改时,我可以强制执行此操作。之后,标识始终具有AppIdentity
类型,而不再是ClaimsIdentity
。
问题:这种方法是否将Cookie中的自定义声明身份类型保存错误且可能不受支持?会话cookie是否存储了派生AppIdentity
的类型信息(我想,这是必要的,以便从cookie中实现正确的身份类型)?
答案 0 :(得分:3)
在序列化往返过程中,类型标识会丢失。我在这里写到: http://leastprivilege.com/2012/10/08/custom-claims-principals-in-net-4-5/
答案 1 :(得分:0)
您可以实现一个简单的HttpModule
来检查主体中的传入标识,并将其转换为您自己的实现
public class MyClaimsAuthenticationModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PostAuthenticateRequest += Context_PostAuthenticateRequest;
}
public void Dispose()
{
// Nothing to dispose, method required by IHttpModule
}
void Context_PostAuthenticateRequest(object sender, EventArgs e)
{
var transformer = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;
if (transformer != null)
{
var context = ((HttpApplication)sender).Context;
var principal = context.User as ClaimsPrincipal;
var oo = principal.Identity is DaIdentity;
if (!oo)
principal = new ClaimsPrincipal(new DaIdentity(principal.Identity as ClaimsIdentity));
var transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, principal);
context.User = transformedPrincipal;
Thread.CurrentPrincipal = transformedPrincipal;
}
}
}
然后在Web.config中注册它,就像这样
<modules runAllManagedModulesForAllRequests="true">
<add name="TestAuthenticationModule" Type="MyAssemby.MyClaimsAuthenticationModule, MyAssembly" preCondition="managedHandler" />
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
<add name="ClaimsAuthorizationModule" type="System.IdentityModel.Services.ClaimsAuthorizationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
<remove name="FormsAuthentication" />
<remove name="WebDAVModule" />
</modules>