Asp.net mvc 3 如何在MVC3中的Unity中设置环境上下文DI?

Asp.net mvc 3 如何在MVC3中的Unity中设置环境上下文DI?,asp.net-mvc-3,dependency-injection,unity-container,Asp.net Mvc 3,Dependency Injection,Unity Container,我目前在使用Windows身份验证的Mvc3应用程序中使用Unity with Unity.Mvc3。我也在阅读有关依赖注入的内容,并试图为一些授权检查设置一个环境上下文 我有一个抽象的AuthorizeContext类,其静态属性Current包含该类的三个实现之一: AuthorizeRoleContext,用于生产,它通过构造函数注入获取字符串和IPrincipal,并且只是一个间接层,用于在发出授权请求或需求时调用IPrincipal.IsUserInRole。注入的字符串用作角色的域前

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

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

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

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

  • AuthorizeContextAllowNothing,用于测试允许的最小功能,它始终拒绝所有授权请求

  • 将来,再添加一个并通过数据库检查授权

  • 因此,我可以通过以下操作(例如,在应用程序_BeginRequest中)手动连接事情:

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

    然后打电话

    AuthorizeContext.Current.Demand(“someRole”)

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

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

    • 我在应用程序启动时没有HttpContext.Current.User,因此当时无法将其注入AuthorizeRoleContext
    • 我不知道如何将实现分配给static AuthorizeContext.Current属性
    现在,也许我应该在任何地方执行[Authorize(Roles=“Role1”)],让MVC3完成它的工作,但是:

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

    但也许我在这方面仍然走错了方向,我正在解决那些不存在的问题。:)

    我不相信这个额外的间接层会增加任何价值。IPrincipal已经是一种多态类型,所以您可以用一种更简单的方式完全实现您想要的

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

    除了AuthorizationContextAllowall,您可以像这样实现IPrincipal:

    public AllowAllPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return true;
        }
    
        // also implement the Identity property...
    }
    
    public AllowNothingPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return false;
        }
    
        // also implement the Identity property...
    }
    
    this.container.RegisterType<IPrincipal>(
        new InjectionFactory(
            _ => HttpContext.Current.User));
    
    与AuthorizeContextAllown不同的是,实现IPrincipal的方式如下:

    public AllowAllPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return true;
        }
    
        // also implement the Identity property...
    }
    
    public AllowNothingPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return false;
        }
    
        // also implement the Identity property...
    }
    
    this.container.RegisterType<IPrincipal>(
        new InjectionFactory(
            _ => HttpContext.Current.User));
    
    要配置它,您可以将其添加到Global.asax.cs:

    private void OnAuthenticateRequest(object sender, EventArgs e)
    {
        this.Context.User = this.container.Resolve<IPrincipal>();
    }
    
    AuthenticateRequest上的私有void(对象发送方,事件参数e)
    {
    this.Context.User=this.container.Resolve();
    }
    
    要使用“real”IPrincipal配置Unity,可以如下设置:

    public AllowAllPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return true;
        }
    
        // also implement the Identity property...
    }
    
    public AllowNothingPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return false;
        }
    
        // also implement the Identity property...
    }
    
    this.container.RegisterType<IPrincipal>(
        new InjectionFactory(
            _ => HttpContext.Current.User));
    
    this.container.RegisterType(
    新注射厂(
    _=>HttpContext.Current.User));
    
    使用AllowAllPrincipal配置Unity要容易得多:

    this.container.RegisterType<IPrincipal, AllowAllPrincipal>();
    
    this.container.RegisterType();
    
    同样,对于Allownothing Principal:

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

    如果您必须坚持连接您自己的上下文,您可以用类似的方式来连接。

    我不相信这个额外的间接层会增加任何价值。IPrincipal已经是一种多态类型,所以您可以用一种更简单的方式完全实现您想要的

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

    除了AuthorizationContextAllowall,您可以像这样实现IPrincipal:

    public AllowAllPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return true;
        }
    
        // also implement the Identity property...
    }
    
    public AllowNothingPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return false;
        }
    
        // also implement the Identity property...
    }
    
    this.container.RegisterType<IPrincipal>(
        new InjectionFactory(
            _ => HttpContext.Current.User));
    
    与AuthorizeContextAllown不同的是,实现IPrincipal的方式如下:

    public AllowAllPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return true;
        }
    
        // also implement the Identity property...
    }
    
    public AllowNothingPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return false;
        }
    
        // also implement the Identity property...
    }
    
    this.container.RegisterType<IPrincipal>(
        new InjectionFactory(
            _ => HttpContext.Current.User));
    
    要配置它,您可以将其添加到Global.asax.cs:

    private void OnAuthenticateRequest(object sender, EventArgs e)
    {
        this.Context.User = this.container.Resolve<IPrincipal>();
    }
    
    AuthenticateRequest上的私有void(对象发送方,事件参数e)
    {
    this.Context.User=this.container.Resolve();
    }
    
    要使用“real”IPrincipal配置Unity,可以如下设置:

    public AllowAllPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return true;
        }
    
        // also implement the Identity property...
    }
    
    public AllowNothingPrincipal : IPrincipal
    {
        public bool IsInRole(string role)
        {
            return false;
        }
    
        // also implement the Identity property...
    }
    
    this.container.RegisterType<IPrincipal>(
        new InjectionFactory(
            _ => HttpContext.Current.User));
    
    this.container.RegisterType(
    新注射厂(
    _=>HttpContext.Current.User));
    
    使用AllowAllPrincipal配置Unity要容易得多:

    this.container.RegisterType<IPrincipal, AllowAllPrincipal>();
    
    this.container.RegisterType();
    
    同样,对于Allownothing Principal:

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

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

    如果不涉及Unity,你会怎么做?何时何地分配当前属性?如果您自己分配,为什么不使用Thread.CurrentPrincipal和现有的框架支持呢?组合根将是Application\u Start,因此我将尝试在这里进行分配。但是需要一个上下文,我想我可以在应用程序_BeginRequest.All AuthorizeRoleContext.Demand中使用IPrinciple.IsInRole,但我想换成其他实现,比如AuthorizeContextAllowAll或AuthorizeContextAllowNothing。我不知道AuthorizeContextAllowAll或AuthorizeContextAllowNothing是什么意思,但是如果IPrincipal太有限,为什么不通过实现IAAuthorizationFilter来连接MVC授权模型呢?如果没有团结,你会怎么做?何时何地分配当前属性?为什么不使用Thread.CurrentPrincipal和现有属性