ClaimsAuthenticationManager.Authenticate 从未被调用
ClaimsAuthenticationManager.Authenticate never gets called
我想在身份验证期间向委托人添加一些额外的声明。我正在尝试在我的 MVC 4.5 项目中实现自定义 ClaimsAuthenticationManager,该项目使用 Windows Authentication:
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 设置为使用我的自定义 class:
<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 方法永远不会被调用。我错过了什么吗?
您是否使用类似的方式调用 Authenticate 方法,但未进行身份验证?
ClaimsTransformer manager = new ClaimsTransformer();
manager.Authenticate("resource", incomingPrincipal )
您可能希望将 ClaimsTransformer class 中的 "return incomingPrincipal" 替换为调用:
return base.Authenticate(resourceName, incomingPrincipal);
另外为什么需要 Windows 身份验证?
缺少的步骤是您需要添加一个 HTTP 模块来启动所有这些。
因此,您需要一个如下所示的 class:
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 中指定的转换器并对其调用身份验证,然后将返回的主体附加到 HttpContext 和当前线程。
您的 web.config 中还需要类似以下内容:
<system.webServer>
<modules>
<add name="MyClaimsAuthenticationModule" type="MyApplication.MyHttpModels.MyClaimsAuthenticationModule, MyApplicationAssembly" />
</modules>
</system.webServer>
更新
当然,您可以将方法 Context_PostAuthenticationRequest
中的代码放入 Global.asax.cs
class 文件的 PostAuthenticateRequest
处理程序中。但是,我更愿意将 class 的职责保持在较小的范围内,因此我选择了 IHttpModule
的实现,这样模块就可以完成它的工作,并且很明显那是什么,并且它与其他模块分开在管道的各个阶段可能发生的事情。
如果您的 Global.asax.cs 文件很小,那么将代码放在那里没有问题。它应该仍然有效。但是,您在 class 中混合了职责,将来可能会变得笨拙。
我想在身份验证期间向委托人添加一些额外的声明。我正在尝试在我的 MVC 4.5 项目中实现自定义 ClaimsAuthenticationManager,该项目使用 Windows Authentication:
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 设置为使用我的自定义 class:
<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 方法永远不会被调用。我错过了什么吗?
您是否使用类似的方式调用 Authenticate 方法,但未进行身份验证?
ClaimsTransformer manager = new ClaimsTransformer();
manager.Authenticate("resource", incomingPrincipal )
您可能希望将 ClaimsTransformer class 中的 "return incomingPrincipal" 替换为调用:
return base.Authenticate(resourceName, incomingPrincipal);
另外为什么需要 Windows 身份验证?
缺少的步骤是您需要添加一个 HTTP 模块来启动所有这些。
因此,您需要一个如下所示的 class:
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 中指定的转换器并对其调用身份验证,然后将返回的主体附加到 HttpContext 和当前线程。
您的 web.config 中还需要类似以下内容:
<system.webServer>
<modules>
<add name="MyClaimsAuthenticationModule" type="MyApplication.MyHttpModels.MyClaimsAuthenticationModule, MyApplicationAssembly" />
</modules>
</system.webServer>
更新
当然,您可以将方法 Context_PostAuthenticationRequest
中的代码放入 Global.asax.cs
class 文件的 PostAuthenticateRequest
处理程序中。但是,我更愿意将 class 的职责保持在较小的范围内,因此我选择了 IHttpModule
的实现,这样模块就可以完成它的工作,并且很明显那是什么,并且它与其他模块分开在管道的各个阶段可能发生的事情。
如果您的 Global.asax.cs 文件很小,那么将代码放在那里没有问题。它应该仍然有效。但是,您在 class 中混合了职责,将来可能会变得笨拙。