指定 Windows AuthenticationScheme 和角色不起作用
Specifying Windows AuthenticationScheme and Roles Doesn't Work
如何指定 AuthenticationScheme
是 Windows
并检查用户是否是 AD 组的成员?
当我指定 AuthenticationScheme
时,设置 Roles
不再有效,为什么不呢?我该如何解决?
public class SomeController : Controller
{
//this works
[Authorize(Roles = @"SOME.DOMAIN\SOME GROUP")]
public IActionResult SomeAction(){ ... }
//this works
[Authorize(AuthenticationSchemes = "Windows")]
//this doesn't work
//[Authorize(Roles = @"SOME.DOMAIN\SOME GROUP", AuthenticationSchemes = "Windows")]
public ActionResult SomeAction2(){ ... }
}
一些背景
我们有一个名为 SOME GROUP
的广告组,用户必须是该组的成员才能执行某些操作。在 Web 应用程序的其他部分,我们使用 cookie 身份验证,因此我需要在此特定控制器中指定身份验证方法。
Windows 身份验证对每个其他身份验证处理程序都是 different。 ASP.NET 不执行身份验证,windows 组件执行,并向 ASP.NET 核心传递它创建的身份的句柄。它不是为其他身份验证类型设计的,也不是为了与其他身份验证类型混合使用,它是 Windows 和匿名,或者只是 Windows。
不支持将它与其他任何东西混合使用,因此您永远不需要按方案进行限制,即使它确实有效。
事实证明,WindowsIdentity
保存在 HttpContext.User
对象中,允许我们检查 group/role 成员资格。
内联示例
using System.Security.Principal;
[Authorize(AuthenticationSchemes = IISServerDefaults.AuthenticationScheme)]
public ActionResult SomeAction()
{
var windowsIdentity = HttpContext.User.Identity as WindowsIdentity;
var windowsUser = new WindowsPrincipal(windowsIdentity);
var role = "[MY-COMPUTER-NAME || AD GROUP NAME]\[GROUP NAME]";
var inInRole = windowsUser.IsInRole(role);
// todo: if not allowed write code to handle it
return View();
}
政策示例
//AuthorizationHandler<T>
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
if (!(context.User.Identity is WindowsIdentity windowsIdentity))
return Task.CompletedTask;
var windowsUser = new WindowsPrincipal(windowsIdentity);
try
{
var hasRole = windowsUser?.IsInRole(requirement.GroupName) ?? false;
if (hasRole)
context.Succeed(requirement);
}
catch (Exception ex)
{
logger.LogError(ex, "Unable to check groups the user belongs too");
}
return Task.CompletedTask;
}
//IAuthorizationRequirement
public class RoleRequirement : IAuthorizationRequirement
{
public RoleRequirement(string groupName)
{ GroupName = groupName; }
/// <summary>
/// The Windows / AD Group Name that is allowed to call the OMS API
/// </summary>
public string GroupName { get; }
}
//action protected with the policy
[Authorize("Super User Role")]
public IActionResult Contact()
{ return View(); }
//startup.cs
public void ConfigureServices(IServiceCollection services)
{
//pull group name from the config
var securityOptions = Configuration.GetSection("Security").Get<SecurityOptions>();
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddAuthorization(options =>
{
options.AddPolicy("Super User Role", policy =>
{
policy.Requirements.Add(new RoleRequirement(securityOptions.AllowedGroup));
policy.AddAuthenticationSchemes("Windows");
});
});
services.AddSingleton<IAuthorizationHandler, RoleHandler>();
// ...
}
如何指定 AuthenticationScheme
是 Windows
并检查用户是否是 AD 组的成员?
当我指定 AuthenticationScheme
时,设置 Roles
不再有效,为什么不呢?我该如何解决?
public class SomeController : Controller
{
//this works
[Authorize(Roles = @"SOME.DOMAIN\SOME GROUP")]
public IActionResult SomeAction(){ ... }
//this works
[Authorize(AuthenticationSchemes = "Windows")]
//this doesn't work
//[Authorize(Roles = @"SOME.DOMAIN\SOME GROUP", AuthenticationSchemes = "Windows")]
public ActionResult SomeAction2(){ ... }
}
一些背景
我们有一个名为 SOME GROUP
的广告组,用户必须是该组的成员才能执行某些操作。在 Web 应用程序的其他部分,我们使用 cookie 身份验证,因此我需要在此特定控制器中指定身份验证方法。
Windows 身份验证对每个其他身份验证处理程序都是 different。 ASP.NET 不执行身份验证,windows 组件执行,并向 ASP.NET 核心传递它创建的身份的句柄。它不是为其他身份验证类型设计的,也不是为了与其他身份验证类型混合使用,它是 Windows 和匿名,或者只是 Windows。
不支持将它与其他任何东西混合使用,因此您永远不需要按方案进行限制,即使它确实有效。
事实证明,WindowsIdentity
保存在 HttpContext.User
对象中,允许我们检查 group/role 成员资格。
内联示例
using System.Security.Principal;
[Authorize(AuthenticationSchemes = IISServerDefaults.AuthenticationScheme)]
public ActionResult SomeAction()
{
var windowsIdentity = HttpContext.User.Identity as WindowsIdentity;
var windowsUser = new WindowsPrincipal(windowsIdentity);
var role = "[MY-COMPUTER-NAME || AD GROUP NAME]\[GROUP NAME]";
var inInRole = windowsUser.IsInRole(role);
// todo: if not allowed write code to handle it
return View();
}
政策示例
//AuthorizationHandler<T>
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
if (!(context.User.Identity is WindowsIdentity windowsIdentity))
return Task.CompletedTask;
var windowsUser = new WindowsPrincipal(windowsIdentity);
try
{
var hasRole = windowsUser?.IsInRole(requirement.GroupName) ?? false;
if (hasRole)
context.Succeed(requirement);
}
catch (Exception ex)
{
logger.LogError(ex, "Unable to check groups the user belongs too");
}
return Task.CompletedTask;
}
//IAuthorizationRequirement
public class RoleRequirement : IAuthorizationRequirement
{
public RoleRequirement(string groupName)
{ GroupName = groupName; }
/// <summary>
/// The Windows / AD Group Name that is allowed to call the OMS API
/// </summary>
public string GroupName { get; }
}
//action protected with the policy
[Authorize("Super User Role")]
public IActionResult Contact()
{ return View(); }
//startup.cs
public void ConfigureServices(IServiceCollection services)
{
//pull group name from the config
var securityOptions = Configuration.GetSection("Security").Get<SecurityOptions>();
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddAuthorization(options =>
{
options.AddPolicy("Super User Role", policy =>
{
policy.Requirements.Add(new RoleRequirement(securityOptions.AllowedGroup));
policy.AddAuthenticationSchemes("Windows");
});
});
services.AddSingleton<IAuthorizationHandler, RoleHandler>();
// ...
}