统一物业注射液对AuthorizeAttribute [英] Unity Property Injection on AuthorizeAttribute

查看:301
本文介绍了统一物业注射液对AuthorizeAttribute的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想注入依赖关系到一个自定义AuthorizeAttribute如下:

 公共类UserCanAccessArea:AuthorizeAttribute
{
    只读IPermissionService permissionService;    公共UserCanAccessArea():
        这个(DependencyResolver.Current.GetService< IPermissionService>()){}    公共UserCanAccessArea(IPermissionService permissionService)
    {
        this.permissionService = permissionService;
    }    保护覆盖布尔AuthorizeCore(HttpContextBase的HttpContext)
    {
        字符串areaID表示= httpContext.Request.RequestContext.RouteData.Values​​ [areaID表示]作为字符串;        布尔isAuthorized = FALSE;        如果(base.AuthorizeCore(HttpContext的))
            isAuthorized = permissionService.UserCanAccessArea(areaID表示,HttpContext.User中);        返回isAuthorized;
    }
}

这工作,但似乎是解决作为一个单身意味着我得到我的描述的问题透水问题

我想要做的是使用注射财产但是作为我的属性本身没有被统一解决,我无法找到一个方法来配置容器拦截并解决财产。我曾尝试以下内容:

 公共类UserCanAccessArea:AuthorizeAttribute
{
    公共IPermissionService permissionService {搞定;组; }    保护覆盖布尔AuthorizeCore(HttpContextBase的HttpContext)
    {
        字符串areaID表示= httpContext.Request.RequestContext.RouteData.Values​​ [areaID表示]作为字符串;        布尔isAuthorized = FALSE;        如果(base.AuthorizeCore(HttpContext的))
            isAuthorized = permissionService.UserCanAccessArea(areaID表示,HttpContext.User中);        返回isAuthorized;
    }
}

集装箱:

  container.RegisterType< UserCanAccessArea>(新InjectionProperty(permissionService));

但物业在运行时总是空。

有没有人做到了这一点,如果是这样,你有一个例子?


解决方案

您应该prevent做的依赖注入的属性完全。这样做的原因是这篇文章中解释说:在属性依赖注入:不这样做!。综上所述文章解释说:


  • 构造方法注入是不可能的,因为一个属性实例的创建不能被截取;在CLR的控制。

  • 使用属性注入的是脆弱的,应该是prevented。

  • 依赖注入的属性使得它无法核实
    容器的配置的正确性。

  • 像MVC
  • 框架和Web API缓存属性,使得它很容易不小心创建俘虏依赖引起的错误。

您有两个选择:


  1. 请属性被动的,从它的行为(服务)分裂的数据(属性)作为的引用的文章

  2. 把你的属性变成中的不起眼的物件=htt​​ps://stackoverflow.com/a /264697分之29318325>这个答案。这意味着你:

    1. 提取该属性的所有逻辑到包含所有依赖的自定义服务。

    2. 注册该服务在您的容器中。

    3. 让属性的方法( AuthorizeCore 你的情况),这样做无非是解决从服务定位器/ DependencyResolver更多的服务和调用服务的方法。重要的是这里要注意的是,你不能做的构造函数注入,资产注入和服务不能被储存在属性私有状态(因为你已经注意到了)。


要使用哪个选项:


  • 使用选项1,如果你非常热衷到保持你的设计干净,或者你有比你需要应用这种方式的几个属性越多,或者你想申请的属性在不依赖于程序集的定义System.Web.Mvc。

  • ,否则使用选项2。

I am trying to inject a dependancy into a custom AuthorizeAttribute as follows:

    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;
    }
}

This works but seems to be resolving as a singleton meaning I get the problems described in my pervious question

What I'd like to do is use property injection but as my Attribute itself is not resolved by Unity I'm unable to find a way to configure the container to intercept and resolve a property. I have tried the following:

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:

        container.RegisterType<UserCanAccessArea>(new InjectionProperty("permissionService"));

But the property is always null at runtime.

Has anyone achieved this and if so do you have an example?

解决方案

You should prevent doing dependency injection into attributes completely. The reason for this is explained in this article: Dependency Injection in Attributes: don’t do it!. In summary the article explains that:

  • Constructor injection is not possible, because creation of an Attribute instance cannot be intercepted; the CLR is in control.
  • The use of property injection is fragile and should be prevented.
  • Dependency injection into attributes makes it impossible to verify the correctness of the container's configuration.
  • Frameworks like MVC and Web API cache attributes, making it very easy to accidentally create captive dependencies causing bugs.

You have two choices here:

  1. Make the attributes passive, by splitting the data (the attribute) from its behavior (the service) as explained in the referenced article.
  2. Turn your attributes into humble objects as explained in this answer. This means you:

    1. extract all logic from the attribute into a custom service that contains all dependencies.
    2. Register that service in your container.
    3. let the attribute's method (AuthorizeCore in your case) do nothing more than resolving the service from the service locator / DependencyResolver and call the service's method. Important to note here is that you cannot do constructor injection, property injection and the service cannot be stored in the attributes private state (as you already noticed).

Which option to use:

  • Use option 1 if you are very keen into keeping your design clean, or you have more than a few attributes that you need to apply this way, or you want to apply attributes are defined in an assembly that doesn't depend on System.Web.Mvc.
  • Use option 2 otherwise.

这篇关于统一物业注射液对AuthorizeAttribute的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆