【问题标题】:Authorization and Windsor授权和温莎
【发布时间】:2009-11-06 17:33:36
【问题描述】:

我正在尝试实现我的自定义授权属性,例如:

 public class MyCustomAuth : AuthorizeAttribute
{
    private readonly IUserService _userService;

    public MyCustomAuth(IUserService userService)
    {
        _userService= userService;
    }
... continued
 }

我正在使用 Castle Windsor 来自动解决依赖关系。

当我尝试将它用作操作方法的属性时,显然我被要求传递参数,或者我需要一个无参数的构造函数,它应该以某种方式解决它的依赖关系。

我尝试使用属性注入依赖项,但 Windsor 没有注入它。

我现在看到的唯一选择是手动实例化具体对象依赖项,失去 Windsor 的好处。

你会如何解决这个问题?

【问题讨论】:

  • 您没有提供任何关于如何设置温莎城堡的代码示例,而是您使用的是配置文件(粘贴配置文件),或者您是如何注册类型的。

标签: asp.net-mvc dependency-injection castle-windsor authorize


【解决方案1】:

您不能将 DI 与属性一起使用 - 它们是元数据;

public class MyCustomAuth : AuthorizeAttribute
{
    public void OnAuthorization(...)
    {
         IUserService userService = ServiceLocator.Current.GetInstance<IUserService>();
    }
}

了解 Windsor/ServiceLocator here

查看类似问题here

【讨论】:

    【解决方案2】:

    您可以使用自定义 ControllerActionInvoker 并注入属性依赖项(您不能进行构造函数注入,因为框架会处理属性的实例化)。你可以看到blog post I just did on this technique.

    【讨论】:

    • Ronnie 只需确保您遍历所有需要注入的过滤器列表。有 ActionFilters、AuthorizationFilters 等,所以在 GetFilters 方法中使用类似 foreach (var filter in filters.AuthorizationFilters) { this.container.Kernel.InjectProperties(filter); } foreach(filters.ActionFilters 中的 var 过滤器){ this.container.Kernel.InjectProperties(filter); }
    【解决方案3】:

    您没有提供任何城堡代码或配置示例。因此,我假设您是 Castle 的新手并且不熟悉注册流程。

    首先,您要对其执行操作的任何对象都必须通过注册类型来自 Castle Windsor。话虽如此,您尝试将城堡温莎与属性一起使用会走错路 - 因为属性没有在代码中引用,而是反映在上面。因此,没有地方供 IoC(在本例中为温莎城堡)创建对象。

    我这么说是因为你想要完成的事情已经通过不同的方式完成了。首先,把你的依赖注入到你的控制器上。

    public class PostController
    {
      private IUserService _userService;
      public PostController (IUserService userService)
      {
        _userService = userService;
      }
    
      // other logic
    
    }
    

    要让 Castle 工作,您必须注册所有类型。因此,您必须在 Castle Windsor 中注册 IUserService,以及哪些服务实现了该接口。您可以通过在 global.asax 中使用 container.AddComponentWithLifeStyle 的手动过程来执行此操作;或者更优选的方法是使用配置文件。

    使用配置文件,您的 IUserService 将如下所示:

    <?xml version="1.0" encoding="utf-8" ?>
    <castle>
        <components>
            <!--lifestyle="singleton|thread|transient|pooled|webrequest|custom"-->
    
            <component
                id="UserService"
                service="MyMvcProject.IUserService, MyMvcProject"
                type="MyMvcProject.UserService, MyMvcProject"
                lifestyle="transient">
            </component>
        </components>
    </castle>
    

    MyMvcProject 是您的项目的名称,并确保使用确切的命名空间和接口的完全限定名称,以及类型。请提供您实际命名空间的代码示例,否则我们无法为您提供更多帮助。

    在此之前,您需要修改 app.config 或 web.config 以注册 Castle Windsor 的 searchGroup:

    <configSections>
    
        <section name="castle" 
            type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"/>
    
    </configSections>
    
    <castle configSource="castle.config"/>
    

    现在您已全部注册和设置,是时候告诉您的 MVC 应用程序“使用 Castle Windsor 创建我的控制器的每个实例”。这样做意味着 Castle Windsor 作为一个控制反转(又名 IoC)容器,将检查您的控制器的依赖关系,并查看它是否依赖于 IUserService 并实现 UserService 的实例 。 Castle 将查看其注册类型的配置,并查看您已为 IUserService 注册了服务。并且,它将在您的配置文件中看到您要实现实现 IUserService 的具体 UserService 类。因此,当请求对 IUserService 的依赖时,IoC 容器将返回 UserService。

    但在此之前,您必须告诉您的 MVC 应用程序使用您配置的 IoC 容器。您可以通过注册一个新的 ControllerFactory 来做到这一点。为此,请参阅我对这个问题的回答:

    Why is Castle Windsor trying to resolve my 'Content' and 'Scripts' folder as a controller?

    并注意如何注册该代码的 global.asax 部分。效果很好!

    现在,当所有这些都说完之后,您想要授权用户。使用实现表单身份验证的普通 [Authorize],并使用您的 _userService 获取登录用户的任何用户详细信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-15
      • 1970-01-01
      相关资源
      最近更新 更多