如何在 MVC3 中的 Unity 中设置 Ambient Context DI?
我目前在使用 Windows 身份验证的 MVC3 应用程序中使用 Unity 和 Unity.Mvc3。我还在阅读有关进行依赖项注入的内容,并尝试设置环境上下文来进行一些授权检查。
我有一个带有静态属性 Current 的抽象 AuthorizeContext 类,它包含该类的三个实现之一:
AuthorizeRoleContext,用于生产,它通过构造函数注入获取字符串和 IPrincipal,只是调用 IPrincipal 的间接层.IsUserInRole 每当发出授权请求或要求时。注入的字符串用作角色的域前缀。
AuthorizeContextAllowAll,用于开发,有时用于测试,始终允许所有授权请求和要求,使用默认构造函数。
AuthorizeContextAllowNothing,用于测试最小允许功能,始终拒绝所有授权请求。
以后再添加一个并通过数据库检查授权...?
因此,我可以通过执行以下操作来手动连接事物(例如,在 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 做它的事情,但是:
- 我也用它来构建我的菜单,也许想在其他地方使用它用于授权检查。
- 我想用其他实现替换授权检查(例如允许所有),这样我就不必将 Windows 组分配给每个开发人员/测试人员。
- 我似乎必须使用 IPrincipal.IsUserInRole 的角色的域前缀,否则它将无法跨开发/测试/生产工作。当然,生产是在客户环境中,使用完全不同的域名。这就是我将域名配置并注入的原因。
- 我想对东西进行单元测试。
但也许我仍然走在错误的轨道上,并且我正在解决不存在的问题。 :)
I'm currently using Unity with Unity.Mvc3 in my MVC3 application which uses Windows Authentication. I'm also reading up on doing dependency injection and am trying to set up an Ambient Context for some authorization checking.
I have an abstract AuthorizeContext class with a static property Current that holds one of three implementations of this class:
AuthorizeRoleContext, used for production, which takes a string and an IPrincipal through constructor injection and is just a layer of indirection to call IPrincipal.IsUserInRole whenever a request or demand for authorization is made. The injected string is used as a domain prefix for the role.
AuthorizeContextAllowAll, used for development and sometimes testing, which always allows all requests and demands for authorization, using a default constructor.
AuthorizeContextAllowNothing, used for testing minimum allowed functionality, which always denies all requests for authorization.
In the future, add one more and check authorization through a database...?
So I can manually wire things up by doing (for instance, in Application_BeginRequest):
AuthorizeContext.Current = new
AuthorizeRoleContext(HttpContext.Current.User);
and then call
AuthorizeContext.Current.Demand("someRole");
This works great, but I'm looking for the right way (and place) to wire it up with Unity, while avoiding the Service Locator anti-pattern. So my question is: how do I do this?
Some of the challenges I have with Unity registration so far:
- I do not have an HttpContext.Current.User at Application_Start, so I cannot inject it in AuthorizeRoleContext at that time
- I do not know how to assign an implementation to the static AuthorizeContext.Current property
Now maybe I should just do [Authorize(Roles = "Role1")] everywhere and just let MVC3 do its thing, but:
- I also use it to build up my menu and perhaps want to use it in other places for authorization checking.
- I'd like to swap out authorization checking with other implementations (like allow all) so I don't have to assign Windows Groups to each developer/tester.
- I seem to have to use a domain prefix for the role with IPrincipal.IsUserInRole or it won't work across dev/test/production. Ofcourse, production is at the customer environment, using totally different domain names. This is the reason I made the domain name configurable and inject it.
- I'd like to unit test things.
But perhaps I'm still on the wrong track with this and I'm working around problems that aren't there. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不相信这个额外的间接层会增加任何价值。 IPrincipal 已经是多态类型,因此您可以以更简单的方式准确地完成您想要的事情。
您可以只使用 Windows 身份验证 (WindowsPrincipal) 提供的 IPrincipal,而不是 AuthorizeRoleContext。
您可以像这样实现 IPrincipal,而不是 AuthorizeContextAllowAll
:
要配置它,您可以将其添加到 Global.asax.cs:
要使用“真正的”IPrincipal 配置 Unity,您可以像这样设置这个:
使用AllowAllPrincipal配置Unity要容易得多:
同样使用AllowNothingPrincipal:
如果你必须坚持连接你自己的AuthorizeContext,你可以这样做所以以类似的方式。
I'm not convinced that this extra layer of indirection adds any value. IPrincipal is already a polymorphic type, so you could accomplish exactly what you want in a much easier way.
Instead of AuthorizeRoleContext you could just use the IPrincipal provided by Windows Authentication (WindowsPrincipal).
Instead of AuthorizeContextAllowAll you could just implement IPrincipal like this:
Instead of AuthorizeContextAllowNothing implement IPrincipal like this:
To configure it, you could add this to Global.asax.cs:
To configure Unity with the 'real' IPrincipal, you can set it up like this:
To configure Unity with the AllowAllPrincipal is much easier:
and likewise with AllowNothingPrincipal:
If you must insist on wiring up your own AuthorizeContext, you could do so in a similar fashion.