【问题标题】:Custom Authorization Filter has exception in run time自定义授权过滤器在运行时出现异常
【发布时间】:2022-01-05 12:06:15
【问题描述】:

我正在使用我的自定义授权过滤器,因为它在这里 How do you create a custom AuthorizeAttribute in ASP.NET Core? 但在运行时得到这个错误: “InvalidOperationException:找不到适合类型 'papillon.Common.RoleRequirementFilter' 的构造函数。确保类型是具体的,并且为公共构造函数的所有参数注册了服务。”。 " 我应该更改我的 startup.cs 中的一些代码吗?!?!

这是我的授权过滤器

public class RoleRequirementFilter : IAuthorizationFilter
{
    private readonly string[] _rolesNames;

    public RoleRequirementFilter(string[] roleNames)
    {
        _rolesNames = roleNames;
    }
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (context.HttpContext.User.IsInRole("Support"))
            return;

        foreach (var item in _rolesNames)
            if (context.HttpContext.User.IsInRole(item))
                return;

        context.Result = new ForbidResult();
        // context.Result = new UnauthorizedResult();
    }
}

这是我的 TypeFilterAttribute

public class RoleRequirementAttribute : TypeFilterAttribute
{
    public RoleRequirementAttribute(string[] roleNames) : base(typeof(RoleRequirementFilter))
    {
        Arguments = roleNames;
    }
}

这是我的 startup.cs

services.AddControllersWithViews().AddRazorRuntimeCompilation();

// ...

app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}").RequireAuthorization();

    endpoints.MapRazorPages().RequireAuthorization();
});

这就是我在控制器中使用它的方式

[RoleRequirement(roleNames:new string[]{Roles.Admin1, Roles.Admin2, Roles.Center1})]

【问题讨论】:

    标签: c# asp.net-core authentication asp.net-core-mvc authorization


    【解决方案1】:

    TypeFilterAttribute.Arguments 是将传递给您正在构建的过滤器的构造函数的对象数组。您的过滤器有一个构造函数参数roleNames,它恰好是一个字符串数组。但是通过设置Arguments = roleNames,您实际上是在告诉框架将每个角色名称作为单独的参数传递给过滤器的构造函数。但是由于您的过滤器没有可变数量的字符串参数(而只是一个字符串数组参数),所以这将不匹配。

    因此,您应该调整类型过滤器以将字符串数组本身作为唯一参数传递给您的过滤器:

    public class RoleRequirementAttribute : TypeFilterAttribute
    {
        public RoleRequirementAttribute(string[] roleNames) : base(typeof(RoleRequirementFilter))
        {
            Arguments = new object[] { roleNames };
        }
    }
    

    【讨论】:

    • 谢谢你,现在我在将它用于控制器时遇到了另一个问题,[AllowAnonymous] 不起作用
    • @Soheil 如果存在[AllowAnonymous],则默认情况下不会跳过自定义授权过滤器。如果您想将该行为应用于您的授权过滤器,则必须以与[Authorize] 过滤器相同的方式显式检查它。见this answer on how to do that
    【解决方案2】:

    您可以将您的角色定义为枚举,然后使用 ResultFilterAttribute 来接受任何这样的 inRole 用户:

    public class UserAuthorization : ResultFilterAttribute
        {
            RolesEnum[] _roles;
            public UserAuthorization(RolesEnum[] roles)
            {
                _roles = roles;
            }
            public override void OnResultExecuting(ResultExecutingContext context)
            {
               
                // if not in role throw exception
                base.OnResultExecuting(context);
    
            }
        }
    

    在上面的任何控制器中,你都可以像这样使用这个属性:

    [UserAuthorization(new RolesEnum[] { RolesEnum.Admin1, RolesEnum.Branch1,RolesEnum.Center1 })]
        public class MyController : Controller
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 2013-03-26
      • 1970-01-01
      相关资源
      最近更新 更多