C# Asp Net Core 3.1自定义角色授权
我在上看到了与NetCore2.2基本相同的问题。 当我尝试为我的NetCore3.1应用程序实现时,我遇到了一个错误C# Asp Net Core 3.1自定义角色授权,c#,asp.net-core-3.1,C#,Asp.net Core 3.1,我在上看到了与NetCore2.2基本相同的问题。 当我尝试为我的NetCore3.1应用程序实现时,我遇到了一个错误 System.InvalidCastException: Unable to cast object of type 'System.Security.Claims.ClaimsIdentity' to type 'System.Security.Principal.WindowsIdentity' RoleAuthHandler.cs尝试将标识强制转换为WindowsIde
System.InvalidCastException: Unable to cast object of type 'System.Security.Claims.ClaimsIdentity' to type 'System.Security.Principal.WindowsIdentity'
RoleAuthHandler.cs尝试将标识强制转换为WindowsIdentity时出错
我想知道核心2.2和3.1之间是否有变化可以解释这一点,或者我做错了什么。任何帮助都会很好
Startup.cs包含
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<IAuthorizationHandler, RoleAuthHandler>();
services.AddAuthorization(options =>
options.AddPolicy(
Role.Admin,
policy => policy.AddRequirements(new RoleRequirement(Role.Admin))));
}
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
RoleRequirement requirement)
{
var wi = (WindowsIdentity)context.User.Identity;
var groupSet = new HashSet<string>();
if (wi.Groups != null)
{
foreach (var group in wi.Groups)
{
groupSet.Add(group.Translate(typeof(NTAccount)).ToString());
}
}
string[] userRoles = roleService.GetRolesForGroup(groupSet);
var intersectRoles = Enumerable.Intersect(userRoles, requirement.Roles, StringComparer.OrdinalIgnoreCase);
if (intersectRoles.Count() > 0)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
RoleRequirement.cs
public class RoleRequirement : IAuthorizationRequirement
{
public string[] Roles { get; }
public RoleRequirement(params string[] roles)
{
this.Roles = roles;
}
}
RoleAuthHandler.cs包含
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<IAuthorizationHandler, RoleAuthHandler>();
services.AddAuthorization(options =>
options.AddPolicy(
Role.Admin,
policy => policy.AddRequirements(new RoleRequirement(Role.Admin))));
}
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
RoleRequirement requirement)
{
var wi = (WindowsIdentity)context.User.Identity;
var groupSet = new HashSet<string>();
if (wi.Groups != null)
{
foreach (var group in wi.Groups)
{
groupSet.Add(group.Translate(typeof(NTAccount)).ToString());
}
}
string[] userRoles = roleService.GetRolesForGroup(groupSet);
var intersectRoles = Enumerable.Intersect(userRoles, requirement.Roles, StringComparer.OrdinalIgnoreCase);
if (intersectRoles.Count() > 0)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
@谢谢你的提醒。我在某个地方的帖子上看到了这个解决方案,并将其驳回,因为我要查找的信息是“用户属于哪个组”。我没有意识到的是,该信息在索赔实体中是可用的。你的提及让我三思而后行,我找到了答案:
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
RoleRequirement requirement)
{
var claimsIdentity = (ClaimsIdentity)context?.User.Identity;
var userGroups = claimsIdentity.Claims
.Where(x => x.Type.Contains("groupsid", StringComparison.OrdinalIgnoreCase))
.ToList();
if (userGroups == null || !userGroups.Any())
{
return Task.CompletedTask;
}
var groupNames = new HashSet<string>();
foreach (var group in userGroups)
{
var groupName = new SecurityIdentifier(group.Value)
.Translate(typeof(NTAccount))
.ToString();
groupNames.Add(groupName);
}
var userRoles = this.authenticationService.GetRoles(groupNames.ToArray());
// If the user is an Admin, always allow
if (userRoles.Contains(Role.Admin))
{
context.Succeed(requirement);
return Task.CompletedTask;
}
var intersectingRoles = Enumerable.Intersect(
userRoles,
requirement?.Roles,
StringComparer.OrdinalIgnoreCase);
if (intersectingRoles?.Count() > 0)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
受保护的覆盖任务句柄请求同步(
授权HandlerContext上下文,
角色(要求)
{
var claimsIdentity=(claimsIdentity)context?.User.Identity;
var userGroups=claimsIdentity.Claims
.Where(x=>x.Type.Contains(“groupsid”,StringComparison.OrdinalIgnoreCase))
.ToList();
if(userGroups==null | |!userGroups.Any())
{
返回Task.CompletedTask;
}
var groupNames=newhashset();
foreach(userGroups中的var组)
{
var groupName=新的SecurityIdentifier(group.Value)
.翻译(类型(NTAccount))
.ToString();
groupName.Add(groupName);
}
var userRoles=this.authenticationService.GetRoles(groupNames.ToArray());
//如果用户是管理员,则始终允许
if(userRoles.Contains(Role.Admin))
{
成功(要求);
返回Task.CompletedTask;
}
var intersectingRoles=Enumerable.Intersect(
用户角色,
要求?角色,
普通木糖酶);
if(intersectingRoles?.Count()>0)
{
成功(要求);
}
返回Task.CompletedTask;
}
你能检查一下这行代码varwi=(WindowsIdentity)context.User.Identity
你应该在你的cas中返回ClaimsIdentity
你需要更改为wi=(ClaimsIdentity)context.User.Identity
。我在从2.2迁移到3.1时遇到同样的问题,但是我看到的ClaimsIdentity
有一个空的Claims
集合,没有Name
,那么我如何获得Windows用户信息呢?@lesscode我和你有同样的问题。我在IIS上运行asp.net核心web应用程序,web应用程序被配置为接受匿名身份验证。禁用此选项,只保留Windows身份验证可用,确保声明是Windows标识的声明之一。@MortenNørgaard不幸的是,我们的控制器混合了已验证和匿名端点,因此我们需要在IIS中启用这两种方案。我仍然认为这是一个突破性的变化,但我们能够通过在自定义处理程序的顶部添加代码来解决这个问题,该处理程序会使经过身份验证的请求提前失败(导致对客户端的质询)。详情如下: