如何在MVC3中的Unity中设置环境上下文DI



我目前在使用Windows身份验证的Mvc3应用程序中使用Unity with Unity.Mvc3。我也在阅读关于进行依赖注入的文章,并试图设置一个环境上下文来进行一些授权检查。

我有一个抽象的AuthorizeContext类,它具有静态属性Current,它包含该类的三个实现之一:

  1. AuthorizeRoleContext,用于生产,它通过构造函数注入获得一个字符串和一个IPrincipal,并且只是一层间接层,用于在请求或要求授权时调用IPrincipal.IsUserInRole。注入的字符串用作角色的域前缀。

  2. AuthorizeContextAllowAll,用于开发,有时用于测试,它总是使用默认构造函数允许所有授权请求和要求。

  3. AuthorizeContextAllowNothing,用于测试允许的最低功能,该功能始终拒绝所有授权请求。

  4. 将来,再添加一个并通过数据库检查授权。。。?

因此,我可以通过以下操作手动连接(例如,在Application_BeginRequest中):

AuthorizeContext.Current=新建AuthorizeRoleContext(HttpContext.Current.User);

然后呼叫

AuthorizeContext.Current.Demand("someRole");

这很好,但我正在寻找正确的方式(和位置)将其与Unity连接起来,同时避免使用服务定位器反模式。所以我的问题是:我该怎么做?

到目前为止,我在Unity注册方面面临的一些挑战:

  • 我在Application_Start中没有HttpContext.Current.User,因此当时无法将其注入AuthorizeRoleContext
  • 我不知道如何将实现分配给静态AuthorizeContext.Current属性

现在,也许我应该到处做[Authorize(Roles="Role1")],让MVC3做它的事情,但是:

  • 我也用它来构建我的菜单,也许还想在其他地方使用它来进行授权检查
  • 我想把授权检查换成其他实现(比如allow-all),这样我就不必为每个开发人员/测试人员分配Windows组
  • 我似乎必须为具有IPrincipal.IsUserInRole的角色使用域前缀,否则它将无法在dev/test/production中工作。当然,生产是在客户环境中进行的,使用完全不同的域名。这就是我使域名可配置并注入它的原因
  • 我想对事物进行单元测试

但也许我仍然走错了路,我正在解决不存在的问题。:)

我不相信这个额外的间接层会增加任何值。IPrincipal已经是一种多态类型,所以你可以用一种更容易的方式来完成你想要的。

您可以只使用Windows身份验证(WindowsPrincipal)提供的IPrincipal,而不是AuthorizeRoleContext。

您可以像这样实现IPrincipal,而不是AuthorizeContextAllowAll:

public AllowAllPrincipal : IPrincipal
{
    public bool IsInRole(string role)
    {
        return true;
    }
    // also implement the Identity property...
}

代替AuthorizeContextAllowNothing实现如下IPrincipal:

public AllowNothingPrincipal : IPrincipal
{
    public bool IsInRole(string role)
    {
        return false;
    }
    // also implement the Identity property...
}

要配置它,您可以将其添加到Global.asax.cs:

private void OnAuthenticateRequest(object sender, EventArgs e)
{
    this.Context.User = this.container.Resolve<IPrincipal>();
}

要用"真正的"IPrincipal配置Unity,你可以这样设置:

this.container.RegisterType<IPrincipal>(
    new InjectionFactory(
        _ => HttpContext.Current.User));

使用AllowAllPrincipal配置Unity要容易得多:

this.container.RegisterType<IPrincipal, AllowAllPrincipal>();

同样,AllowNothingPrincipal:

this.container.RegisterType<IPrincipal, AllowNothingPrincipal>();

如果你必须坚持连接你自己的AuthorizeContext,你可以用类似的方式。

最新更新