c# - 将依赖项注入(inject)类库中的 AuthorizeAttribute

标签 c# .net asp.net-mvc-3 dependency-injection

我在编写的类库中遇到了一个有趣的设计问题。我有一个 AuthorizeAttribute 的自定义实现,我希望客户能够像这样使用它:

[Protected("permission_name")] 

在上面的代码中,PermissionAttribute 继承自 AuthorizeAttribute 并使用本地默认值(使用 HttpContext 创建的 DefaultContext)。

在幕后,该属性使用 SecurityService 来检查用户、角色和权限(SecurityService 本身使用客户端提供的持久性服务,他们可以将其连接到其应用程序的组合根中)。

所以我的属性需要引用 SecurityService 才能起作用。由于属性构造函数只能有编译时常量,我不能使用构造函数注入(inject)。

我不想强制我的客户使用 DI 框架 - 他们应该能够发现连接他们的组合根中的必要依赖关系IoC 库,如果他们愿意的话。

这是我的选择:

  • 让图书馆使用单例 SecurityService。
  • 使用属性注入(inject),这会起作用但是
    1. 它会使依赖关系看起来是可选的,但事实并非如此
    2. 我不知道在 MVC 应用程序中的什么地方可以对授权属性进行属性注入(inject)。

上述 2. 的可能解决方案是在应用程序启动时将 SecurityService 的实例设置为属性的静态属性,并使用保护子句来防止它被设置多次,如下所示:

class ProtectedAttribute : ...
{
    private static ISecurityService _SecurityService ;
    public static ISecurityService SecurityService
    {
        get 
        {
            return _SecurityService ;
        }
        set 
        {
            if (_SecurityService != null)
                throw new InvalidOperationException("You can only set the SecurityService once per lifetime of this app.") ;
            _SecurityService = value ;
        }
    }
}

SecurityService 可以是一个抽象的服务门面,这样它就可以被不同的实现扩展/替换。

有没有更好的办法解决这个问题?

更新:添加一些代码来展示我将如何做:

在返回权限名称的属性上添加一个公共(public)属性:

public class ProtectedAttribute : ...
{
  private string _Permission ;
  public string Permission { get { return _Permission ; } /*...*/ }

  public ProtectedAttribute(string permission) { /*...*/ }
}

设置授权过滤器并通过 Ninject 配置依赖项(如果使用 Ninject):

using Ninject.Web.Mvc.FilterBindingSyntax;

public class MyModule : Ninject.Modules.NinjectModule
{
  public override void Load()
  {
    // mySecurityService instance below can have a singleton lifetime - perfect!
    this.BindFilter<MyAuthorizationFilter>(FilterScope.Action, 0)
        .WhenActionMethodHas<ProtectedAttribute>()
        .WithConstructorArgument("securityService", mySecurityService)
        .WithConstructorArgumentFromActionAttribute<ProtectedAttribute>("permission", p => p.PermissionName) ;
  }
}

哦,这是......美丽的吸 Nose

最佳答案

借助新的 IFilterProvider,您可以在 ASP.NET MVC 3 中使用带有操作过滤器的构造函数注入(inject).这样你就不再需要用 Action 过滤器来装饰你的 Controller Action 了。由于这个界面并使用标记属性,您可以应用它们。

如果您不想手动实现它,您总是可以使用现有的 DI 框架,例如 Ninject,它提供了 fluent way定义操作过滤器依赖项。

关于c# - 将依赖项注入(inject)类库中的 AuthorizeAttribute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8760339/

相关文章:

c# - X.ToCharArray().Length 等于 GetBytes(X).Length

c# - 您将如何使用 Scala 的异步使多个异步请求超时?

c# - 发送多个按键 WatiN

c# - mscorlib.dll 中的 System.UnauthorizedAccessException

.net - 如何使用HttpModule记录请求输入流,然后重置InputStream位置

asp.net-mvc-3 - ASP.NET MVC 3 应用程序的按抽象分支的示例,其中抽象位于不同的国家/地区

css - MVC3 条件行样式以及 CSS 老虎条纹

c# - 何时在 C# 中无约束地使用泛型方法?

c# - 在哪里安全地存储来自 Windows 服务的数据?

JQuery Unobtrusive Validation 在不应该触发的情况下触发下拉列表