asp.net-mvc-3 - 如何在 MVC3 中的 Unity 中设置 Ambient Context DI?

标签 asp.net-mvc-3 dependency-injection unity-container

我目前在使用 Windows 身份验证的 MVC3 应用程序中使用 Unity 和 Unity.Mvc3。我还在阅读有关进行依赖项注入(inject)的内容,并尝试设置环境上下文来进行一些授权检查。

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

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

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

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

  4. 以后再添加一个并通过数据库检查授权...?

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

AuthorizeContext.Current = new AuthorizeRoleContext(HttpContext.Current.User);

然后调用

AuthorizeContext.Current.Demand("someRole");

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

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

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

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

  • 我还使用它来构建我的菜单,并且可能想在其他地方使用它进行授权检查。
  • 我希望将授权检查替换为其他实现(例如允许全部),这样我就不必将 Windows 组分配给每个开发人员/测试人员。
  • 我似乎必须使用 IPrincipal.IsUserInRole 角色的域前缀,否则它将无法跨开发/测试/生产工作。当然,生产是在客户环境中使用完全不同的域名。这就是我将域名配置并注入(inject)的原因。
  • 我想对一些东西进行单元测试。

但也许我仍然走在错误的轨道上,并且我正在解决不存在的问题。 :)

最佳答案

我不相信这个额外的间接层会增加任何值(value)。 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,您可以以类似的方式执行此操作。

关于asp.net-mvc-3 - 如何在 MVC3 中的 Unity 中设置 Ambient Context DI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8817528/

相关文章:

c# - ASP.Net C# 如何使网站上的页面在通过登录进行身份验证后可访问

java - Spring接口(interface)注入(inject)示例

c# - 如何将 Owin 上下文传递给被注入(inject) Api Controller 的 Repo

c# - 我应该使用 OwinContext 的环境来保存每个请求的应用程序特定数据吗

asp.net-mvc-3 - 我应该在 MVC3 和 ASP.net 中尝试 F# 吗?

javascript - 如何从 jquery 中的字符串获取原始 html?

java - 我应该使用 RoboGuice 还是其他依赖注入(inject)框架?

c# - Dotnet Core 是否实现组合根发现?

exception - Unity应用程序 block : Exception occurred while resolving: BadImageFormatException

c# - 如何将值从 View 传递到 Controller