ClaimsAuthenticationManager.Authenticate永远不会被调用

时间:2015-07-24 19:27:59

标签: c# asp.net-mvc asp.net-mvc-4 wif claims-based-identity

我想在身份验证期间向Principal添加一些额外的声明。我正在尝试在我的MVC 4.5 项目中实现自定义ClaimsAuthenticationManager,该项目使用 Windows身份验证

namespace Project.Infrastructure
{
    public class ClaimsTransformer : ClaimsAuthenticationManager
    {
        public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
        {
            if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
            {
                ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "Admin"));
            }

            return incomingPrincipal;
        }
    }
}

我已将web.config设置为使用我的自定义类:

<configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</configSections>

<system.identityModel>
    <identityConfiguration>
      <claimsAuthenticationManager type="Project.Infrastructure.ClaimsTransformer, [AssemblyName]" />
    </identityConfiguration>
</system.identityModel>

Authenticate 方法永远不会被调用。我错过了什么吗?

2 个答案:

答案 0 :(得分:5)

缺少的一步是你需要添加一个HTTP模块来解决所有这些问题。

所以,你需要一个看起来像这样的类:

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 transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, principal);

            context.User = transformedPrincipal;
            Thread.CurrentPrincipal = transformedPrincipal;
        }
    }
}

这将获取您在web.config中指定的变换器并在其上调用authenticate,然后将返回的主体附加到HttpContext和当前线程。

您还需要在web.config中使用以下内容:

<system.webServer>
  <modules>
    <add name="MyClaimsAuthenticationModule" type="MyApplication.MyHttpModels.MyClaimsAuthenticationModule, MyApplicationAssembly" />
  </modules>
</system.webServer>

<强>更新

当然,您可以将方法Context_PostAuthenticationRequest中的代码放在PostAuthenticateRequest类文件中的Global.asax.cs处理程序中。但是,我更喜欢保持类的职责小,所以我去实现IHttpModule,以便模块完成它的事情,这很明显是什么,它与其他可能发生的事情是分开的在管道的各个阶段。

如果您的Global.asax.cs文件很小,那么将代码放在那里就没有问题。它应该仍然有效。但是,你在课堂上混合责任,将来可能会变得笨拙。

答案 1 :(得分:0)

您是否使用类似的方式调用Authenticate方法,并且未进行身份验证?

ClaimsTransformer manager = new ClaimsTransformer();
manager.Authenticate("resource", incomingPrincipal )

您可能希望通过调用来替换ClaimsTransformer类中的“return incomingPrincipal”:

return base.Authenticate(resourceName, incomingPrincipal);

另外,为什么还需要Windows身份验证?