我正在尝试将依赖项注入自定义AuthorizeAttribute
,如下所示:
public class UserCanAccessArea : AuthorizeAttribute
{
readonly IPermissionService permissionService;
public UserCanAccessArea() :
this(DependencyResolver.Current.GetService<IPermissionService>()) { }
public UserCanAccessArea(IPermissionService permissionService)
{
this.permissionService = permissionService;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string AreaID =
httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string;
bool isAuthorized = false;
if (base.AuthorizeCore(httpContext))
isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User);
return isAuthorized;
}
}
这有效,但似乎是作为单身人士解决,这意味着我得到了pervious question
中描述的问题我想要做的是使用属性注入,但由于我的属性本身未被Unity解析,我无法找到配置容器来拦截和解析属性的方法。我尝试过以下方法:
public class UserCanAccessArea : AuthorizeAttribute
{
public IPermissionService permissionService { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string AreaID =
httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string;
bool isAuthorized = false;
if (base.AuthorizeCore(httpContext))
isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User);
return isAuthorized;
}
}
容器:
container.RegisterType<UserCanAccessArea>(new InjectionProperty("permissionService"));
但是该属性在运行时始终为null。
有没有人实现过这个目标?如果有,你有一个例子吗?
答案 0 :(得分:41)
您应该防止完全依赖注入属性。本文解释了原因:Dependency Injection in Attributes: don’t do it!。总之,文章解释说:
你有两个选择:
AuthorizeCore
)除了从服务定位器/ DependencyResolver解析服务并调用服务的方法之外什么都不做。这里要注意的重要一点是,你不能做构造函数注入,属性注入和服务不能存储在属性私有状态(正如你已经注意到的)。使用哪个选项:
答案 1 :(得分:1)
在 ASP.NET Core 中,现在可以通过创建自定义属性,实现IFilterFactory或使用TypeFilterAttribute以及{{3} }。
两者都实现了IFilterFactory
,并且执行了在实现IFilterFactory
的自定义属性中通常要做的事情,唯一的区别是它们都支持排序(可以根据需要在自定义属性中添加)
但更具体地说-ServiceFilterAttribute
从实际服务集合中获取过滤器的实例,这使您可以为其定义特定的生存期,而TypeFilterAttribute
并不使用服务集合来创建您的过滤器对象,它使用ServiceFilterAttribute方法的结果Microsoft.Extensions.DependencyInjection.ObjectFactory。 (基本上,它创建了带有很多表达式树的对象。)TypeFilterAttribute
还允许您传递非服务构造函数参数的参数。两者都将服务集合用于任何DI。
对于您现有的代码库,您可以非常简单地执行以下任一操作以在属性的构造函数中实现依赖注入:
[TypeFilter(typeof(MyExistingFilterWithConstructorDI))]
[TypeFilter(typeof(MyExistingFilterWithConstructorDIAndParams), Arguments = new object[] { "first non-service param", "second non-service param" })]
[ServiceFilter(typeof(MyExistingFilterWithConstructorDI))
(您需要在适当的生命周期内将过滤器注册到服务集合中) 现在,就性能而言,如果最终使用TypeFilterAttribute
,将如上所述创建带有表达式树的过滤器类型,而如果您仅创建自己的IFilterFactory
,您可以控制该部分,即只需实例化对象,并满足任何依赖项注入需求-您可以将提供的IServiceProvider
用作接口CreateInstance
方法的一部分。
作为IsReusable
界面一部分的IFilterFactory
属性可让您显示是否首选框架以在请求范围之外使用对象。这绝不能保证您永远只为过滤器使用单个对象。
答案 2 :(得分:-3)
警报警报警报警报! XD 我是这样实现的:
public class ClaimsHandlerAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var jwtAuthManager = context.HttpContext.RequestServices.GetService(typeof(IJwtAuthManager)) as JwtAuthManager;
return;
}
}