自定义授权过滤器在 运行 时间内出现异常
Custom Authorization Filter has exception in run time
我在这里使用我的自定义授权过滤器
但是在 运行 时间得到这个错误:
“InvalidOperationException:找不到适合类型 'papillon.Common.RoleRequirementFilter' 的构造函数。确保类型是具体的,并且已为 public 构造函数的所有参数注册服务。”。
“
我应该更改 startup.cs 中的一些代码吗?!?!
这是我的 AuthorizationFilter
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})]
您可以将您的角色定义为枚举,然后使用 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
TypeFilterAttribute.Arguments
是将传递给您正在构建的过滤器的构造函数的对象数组。您的过滤器有一个构造函数参数 roleNames
,它恰好是一个字符串数组。但是通过设置 Arguments = roleNames
,您实际上是在告诉框架将 每个角色名称 作为单独的参数传递给过滤器的构造函数。但是由于您的过滤器没有可变数量的字符串参数(只有一个字符串数组参数),因此这将不匹配。
因此,您应该调整类型过滤器以将字符串数组本身作为唯一参数传递给过滤器:
public class RoleRequirementAttribute : TypeFilterAttribute
{
public RoleRequirementAttribute(string[] roleNames) : base(typeof(RoleRequirementFilter))
{
Arguments = new object[] { roleNames };
}
}
我在这里使用我的自定义授权过滤器
这是我的 AuthorizationFilter
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})]
您可以将您的角色定义为枚举,然后使用 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
TypeFilterAttribute.Arguments
是将传递给您正在构建的过滤器的构造函数的对象数组。您的过滤器有一个构造函数参数 roleNames
,它恰好是一个字符串数组。但是通过设置 Arguments = roleNames
,您实际上是在告诉框架将 每个角色名称 作为单独的参数传递给过滤器的构造函数。但是由于您的过滤器没有可变数量的字符串参数(只有一个字符串数组参数),因此这将不匹配。
因此,您应该调整类型过滤器以将字符串数组本身作为唯一参数传递给过滤器:
public class RoleRequirementAttribute : TypeFilterAttribute
{
public RoleRequirementAttribute(string[] roleNames) : base(typeof(RoleRequirementFilter))
{
Arguments = new object[] { roleNames };
}
}