多角色授权处理程序-仅获取方法角色



我正在开发一个。net Core web应用程序,我无法进入工作自定义授权属性处理程序。

我的目标是使自定义授权处理程序处理设置文件(业务需求)。
那么,问题是什么?我将提供尽可能少的代码来解释。

我们从Controller开始

[Authorize(Roles = Roles.Full)]
[Authorize(Roles = Roles.Read)]
public class ConfigurationController : BaseController
{
...

[Authorize(Roles = Roles.Full)]
public async Task<ActionResult> Edit(ServiceConfigurationDto item)
{ .. }
}
目标是只有完整的的用户Access可以保存数据…

()现在在我的处理程序中,当用户单击保存时,我收到3个角色,而不是1。

这是我的处理器

public class RoleRequirementHandler : IAuthorizationHandler
{
public Task HandleAsync(AuthorizationHandlerContext context)
{
var succeed = false;
var pendingRequirements = context.PendingRequirements.ToList();
var requiredRoles = new List<RoleRequirement>();
foreach (var x in pendingRequirements)
{
requiredRoles.AddRange(((RolesAuthorizationRequirement)x).AllowedRoles.Select(x => new RoleRequirement(x)).ToList());
}
foreach (var x in requiredRoles)
{
if (x is RoleRequirement)
{
var prefix = "APPT"; // future from setting file
if (context.User.IsInRole(prefix + ((RoleRequirement)x).Role))
{
succeed = true;
}
}
};
if (succeed)
{
pendingRequirements.ForEach(x => context.Succeed(x));
}

return Task.CompletedTask;
}
}

只有一个角色可以正常工作,但如果使用先前的Edit方法,Handler将获得3个角色,并且无法处理。

...................

添加策略如下:

options.AddPolicy(Roles.Full,
policy => policy.Requirements.Add(new RoleRequirement(Roles.Full)));

对于每个角色,

我也使用Cookie认证方案

我将感谢任何建议:)

这将使用"and"角色中的条件

[Authorize(Roles = Roles.Full)]
[Authorize(Roles = Roles.Read)]

将使用"OR">

[Authorize(Roles = "Full,Read")]

在控制器上尝试像这样指定或条件

[Authorize(Roles = "Full,Read")]

实际上你缺乏逻辑来优先考虑需求。例如:具有Full角色的用户可以跳过其他需求,而具有Read角色的用户只能跳过其他需求优先级较低的(当然不包括Full最优先的角色)。

我知道你的代码是混乱的,这可能是由于你的IAuthorizationHandler的实现不继承AuthorizationHandler<TRequirement>。这里我只是调整了最相关的代码,使其工作(而不是使整个处理程序代码更干净):

var mostPrioritizedRequirement = requiredRoles.Of<RoleRequirement>()
.OrderByDescending(e => e.Role == Roles.Full).FirstOrDefault();
if(mostPrioritizedRequirement != null){
var prefix = "APPT"; // future from setting file
succeed = context.User.IsInRole(prefix + mostPrioritizedRequirement.Role);
}

上面的代码与你的代码相当,似乎只验证了最优先级的需求(在你的代码中,当然第一个succeed = true不会打破循环)。

:从你的问题的标题,似乎你想验证只是最接近的要求(应用于行动方法)。因此,您需要找到当前操作方法(如果有的话)上应用的需求,以确定succeed的值,而不是优先考虑Role。上面的代码仍然是可用的,但是在运行它之前,我们可以先找到当前操作方法上应用的需求,然后验证它,像这样:

var methodRequirements = Enumerable.Empty<RoleRequirement>();
ActionDescriptor currentActionDescriptor = null;
if(context.Resource is Endpoint ep){
currentActionDescriptor = ep.Metadata.GetMetadata<ActionDescriptor>();
} else if(context.Resource is ActionContext ac){
currentActionDescriptor = ac.ActionDescriptor;
}
if(currentActionDescriptor != null){
methodRequirements = currentActionDescriptor.FilterDescriptors
.Select(e => e.Filter)
.Of<AuthorizeFilter>()
.SelectMany(e => e.AuthorizeData ?? Enumerable.Empty<IAuthorizeData>())
.SelectMany(e => e.Roles.Select(o => new RoleRequirement(o))).ToList();                                                   
}    
var mostPrioritizedRequirement = (methodRequirements.Any() ?
methodRequirements : requiredRoles.Of<RoleRequirement>())
.OrderByDescending(e => e.Role == Roles.Full).FirstOrDefault();
if(mostPrioritizedRequirement != null){
var prefix = "APPT"; // future from setting file
succeed = context.User.IsInRole(prefix + mostPrioritizedRequirement.Role);
}

最新更新