我正在开发一个。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);
}