3

在 VS 2012 / .NET 4.5 / ASP.NET MVC 4 应用程序中,我有一个从ClaimsIdentity. 为了方便起见,它只是向基类添加了一些只读属性,这些属性从一些声明中读取值:

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;

...我发现有时运行时类型identityisAppIdentity有时它只是它的基本类型ClaimsIdentity。我的自定义声明始终存在Claimsidentity.

当工作进程被回收时,身份似乎“丢失”了AppIdentity我期望的类型。目前我只在这个项目中使用 IIS Express 开发服务器,例如,当我在 web.config 中做一些小的更改时,我可以强制这种行为。之后,身份始终具有类型ClaimsIdentity,而AppIdentity不再具有。

问题:这种将自定义声明身份类型保存在 cookie 中的方法是否错误并且可能不受支持?会话 cookie 是否存储了派生的类型信息ClaimsIdentity(我猜,这对于从 cookie 中实现正确的身份类型是必要的)?

4

2 回答 2

3

类型标识在序列化往返期间丢失。我在这里写过:http: //leastprivilege.com/2012/10/08/custom-claims-principals-in-net-4-5/

于 2013-04-16T05:20:17.023 回答
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>
于 2017-02-06T14:09:10.220 回答