我目前在使用 Windows 身份验证的 MVC3 应用程序中使用 Unity 和 Unity.Mvc3。我还在阅读有关进行依赖项注入(inject)的内容,并尝试设置环境上下文来进行一些授权检查。
我有一个抽象的 AuthorizeContext 类,其静态属性 Current 包含该类的三个实现之一:
AuthorizeRoleContext,用于生产,它通过构造函数注入(inject)获取字符串和 IPrincipal,并且只是在发出授权请求或要求时调用 IPrincipal.IsUserInRole 的间接层。注入(inject)的字符串用作角色的域前缀。
AuthorizeContextAllowAll,用于开发,有时用于测试,它始终允许所有授权请求和要求,使用默认构造函数。
AuthorizeContextAllowNothing,用于测试允许的最低功能,该功能始终拒绝所有授权请求。
以后再添加一个并通过数据库检查授权...?
因此,我可以通过执行以下操作手动连接事物(例如,在 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/