【问题标题】:Injecting an IPrincipal with Unity Property Injection at runtime在运行时使用 Unity 属性注入注入 IPrincipal
【发布时间】:2011-09-01 21:09:42
【问题描述】:

在 ASP.Net MVC 2 应用程序中使用 Unity 我对正确实例化的控制器有各种依赖关系。但是,我想确保用户的当前 IPrincipal 将通过注入传递到较低级别的服务、存储库等。

因此,在较低级别的服务中,我有类似的东西:

[Dependency] IPrincipal CurrentUser {get; set;}

如果我使用属性依赖注入,我不会得到我想要的,因为控制器是在用户主体可用之前实例化的,并且在任何情况下 Unity 都不知道获取当前用户凭据。

所以我想要的是能够将当前用户的 IPrincipal(或者可能是 RolePrincipal)注入到 Controller 的依赖项之一中。

我该怎么做?

【问题讨论】:

  • 感谢 mrjoltcola 和 mnemosyn 的回答。我同意 cmets 关于依赖注入的观点。我正在研究的想法是让它自动出现在服务和存储库中,这样每次开发人员要更新数据库时,控制器类中就不会有额外的代码。由于这与审计有关,我想确保运行时用户始终可用,并且开发人员不必记住通过它。

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


【解决方案1】:

为什么不走直接路线,然后分配它。

Thread.CurrentPrincipal = 用户;

依赖注入是好的,但不要让它妨碍最好的依赖注入器,程序员。

【讨论】:

  • +1 Thread.CurrentPrincipal 已经是与当前用户打交道的事实标准,很少有理由偏离这个成熟的编码习惯。
  • 应用程序是多层的,极有可能部署到多层中,因此我有一个应用程序 CustomPrincipal 可以通过,以避免对中/后端层的任何污染与 HttpContext 依赖项.假设将有从 Web 演示(MVC 控制器)到中间层服务的 WCF 通信,我可以确定 Thread.CurrentPrincipal 将返回 WebForms 身份验证的 IPrincipal 吗?
【解决方案2】:

虽然这个帖子很旧,但看起来 Jon Kruger 的答案似乎直接回答了原始问题:http://jonkruger.com/blog/2009/04/13/hiding-threadcurrentprincipal-from-your-code/

【讨论】:

    【解决方案3】:

    为什么要注入它?当前主体已作为User 存在。这就是我们使用的,到目前为止它运行良好。用户不应该在一个请求中改变,不是吗?

    protected void Application_AuthenticateRequest()
    {
        var ticket = GetAuthenticationTicket();
        // Perform actual authentication, etc.
        MyUser user = BigAuthStuff();
        Context.User = user;
        Thread.CurrentPrincipal = user;
    }
    
    public class MyBaseController : Controller
    {
        protected MyUser AuthenticatedUser
        {
            get { return User as MyUser; }
        }
    }
    

    【讨论】:

    • 如果网站调用与技术无关的域模型,Context.User 不能很好地工作。域模型尝试访问任何类型的 HTTP 上下文将是一个严重错误。
    • 嗯,确实。但是,我不认为域模型应该与外部的一些静态交互。这个想法是将用户放入上下文中,以便控制器可以使用它。最终,调用域模型的应该是控制器,对吧?也许你可以更进一步说:领域模型根本不应该有关于用户执行代码的概念。如果域模型涉及授权,它只需要包含该功能本身,所以我们必须根据当前用户设置域模型,我们应该在控制器中再次这样做?!
    • 问题是通过 wcf 在多层部署中一直传递凭据,并在自定义主体中带来一些其他属性(例如角色)
    • 嗯,我没有使用过 WCF,所以我很难对此发表评论。也许您应该在最初的问题中这么说?对于“普通”MVC 应用程序,我的方法可以正常工作,并且它在自定义 IPrincipal 中也有角色等。虽然我不得不承认让用户进入Application_AuthenticateRequest() 并不是很聪明,因为通常不需要执行身份验证,即图像。再说一次,使用 CDN 应该没问题...