Asp.net mvc MVC获取/模拟存储库中的Windows用户

Asp.net mvc MVC获取/模拟存储库中的Windows用户,asp.net-mvc,dependency-injection,asp.net-identity,repository-pattern,Asp.net Mvc,Dependency Injection,Asp.net Identity,Repository Pattern,我有一个内部网应用程序,它使用Windows用户名并将其传递给一个过程以返回数据 我正在使用依赖注入,但我不相信我有办法将用户名正确分开 我试图通过不将用户名作为参数传递来保证安全,但我也希望能够模拟(或绕过我的GetWindowsUser()方法)并发送另一个用户名,以便为其他用户测试结果。 我的一个想法是在另一个页面中使用另一个(模拟的)用户名设置一个会话变量,然后在获取实际用户名之前先检查该会话变量是否存在,但我不知道如何访问存储库中的会话变量 WEB API控制器 public cl

我有一个内部网应用程序,它使用Windows用户名并将其传递给一个过程以返回数据

  • 我正在使用依赖注入,但我不相信我有办法将用户名正确分开
  • 我试图通过不将用户名作为参数传递来保证安全,但我也希望能够模拟(或绕过我的GetWindowsUser()方法)并发送另一个用户名,以便为其他用户测试结果。
    • 我的一个想法是在另一个页面中使用另一个(模拟的)用户名设置一个会话变量,然后在获取实际用户名之前先检查该会话变量是否存在,但我不知道如何访问存储库中的会话变量
  • WEB API控制器

    public class DropDownDataController : ApiController
    {
        private IDropDownDataRepository _dropDownDataRepository;        
    
        //Dependency Injection using Unity.WebAPI NuGet Package
        public DropDownDataController(IDropDownDataRepository dropDownDataRepository)
        {
            _dropDownDataRepository = dropDownDataRepository;
        }
    
        [HttpGet]
        public HttpResponseMessage MyList()
        {
            try
            {
                return _dropDownDataRepository.MyList();
            }
            catch
            {
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
        }
    }
    
    public class DropDownDataController : ApiController
    {
        private IDropDownDataRepository _dropDownDataRepository;      
    
        //Dependency Injection using Unity.WebAPI NuGet Package
        public DropDownDataController(IDropDownDataRepository dropDownDataRepository)
        {
            _dropDownDataRepository = dropDownDataRepository;
        }
    
        [HttpGet]
        public HttpResponseMessage MyList()
        {
            try
            {
                var sourceQuery = _dropDownDataRepository.MyList();
    
                //JSON stuff moved to controller
                string result = JsonConvert.SerializeObject(sourceQuery);
                var response = new HttpResponseMessage();
                response.Content = new StringContent(result, System.Text.Encoding.Unicode, "application/json");
    
                return response;
            }
            catch
            {
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
            }
        }
    
        protected override void Dispose(bool disposing)
        {
            _dropDownDataRepository.Dispose();
            base.Dispose(disposing);
        }
    }
    
    存储库

    public class DropDownDataRepository : IDropDownDataRepository, IDisposable
    {
        private DatabaseEntities db = new DatabaseEntities();
    
        public HttpResponseMessage MyList()
        {
            //(This should be separated somehow, right?) 
            //Create a new instance of the Utility class
            Utility utility = new Utility();
            //Grab the windowsUser from the method
            var windowsUser = utility.GetWindowsUser();
    
            //Pass windowsUser parameter to the procedure
            var sourceQuery = (from p in db.myProcedure(windowsUser)
                               select p).ToList();
    
            string result = JsonConvert.SerializeObject(sourceQuery);
            var response = new HttpResponseMessage();
            response.Content = new StringContent(result, System.Text.Encoding.Unicode, "application/json");
    
            return response;            
        }
    }
    
    接口

    public interface IDropDownDataRepository : IDisposable
    {
        HttpResponseMessage MyList();        
    }
    
    public interface IDropDownDataRepository : IDisposable
    {
        //Changed to list here
        List<MyProcedure> MyList();
    }
    
    public interface IUtilityRepository
    {
        string GetWindowsUser();
    }
    
    public interface ISessionRepository
    {
        string ImpersonatedUser { get; }
    }
    
    实用程序类

    public class Utility
    {
        public string GetWindowsUser()
        {
            //Get the current windows user
            string windowsUser = HttpContext.Current.User.Identity.Name;        
    
            return windowsUser;
        }
    }
    
    更新1

    除了Nikolai和Brendt在下面发布的内容外,还需要以下内容来允许Web Api控制器使用会话状态。

    抽象
    实用程序
    类并将其注入存储库。 然后您可以存根或模拟以进行测试

    public interface IUtility
    {
        string GetWindowsUser();
    }
    
    public class TestUtility : IUtility
    {
        public string GetWindowsUser()
        {
            return "TestUser";
        }
    }
    
    public class DropDownDataRepository : IDropDownDataRepository, IDisposable
    {
    
        private IUtility _utility;
    
        public DropDownDataRepository(IUtility utility)
        {
            _utility = utility;
        }
    
    }
    
    编辑

    此外,存储库不应返回
    HTTPResponseMessage
    类型,它只应返回正在访问的域模型的
    列表

    i、 e

    public List MyList()
    {
    //从方法中获取windowsUser
    var windowsUser=_utility.GetWindowsUser();
    //将windowsUser参数传递给过程
    var sourceQuery=(来自db.myProcedure(windowsUser)中的p)
    选择p.ToList();
    返回源查询
    }
    

    然后将JSON部分移动到控制器。

    提取
    实用程序
    类并将其注入存储库。 然后您可以存根或模拟以进行测试

    public interface IUtility
    {
        string GetWindowsUser();
    }
    
    public class TestUtility : IUtility
    {
        public string GetWindowsUser()
        {
            return "TestUser";
        }
    }
    
    public class DropDownDataRepository : IDropDownDataRepository, IDisposable
    {
    
        private IUtility _utility;
    
        public DropDownDataRepository(IUtility utility)
        {
            _utility = utility;
        }
    
    }
    
    编辑

    此外,存储库不应返回
    HTTPResponseMessage
    类型,它只应返回正在访问的域模型的
    列表

    i、 e

    public List MyList()
    {
    //从方法中获取windowsUser
    var windowsUser=_utility.GetWindowsUser();
    //将windowsUser参数传递给过程
    var sourceQuery=(来自db.myProcedure(windowsUser)中的p)
    选择p.ToList();
    返回源查询
    }
    
    然后将JSON部分移动到控制器

    我的一个想法是在另一个页面中设置一个会话变量 使用另一个(模拟的)用户名,然后检查该会话 变量在获取实际用户名之前首先存在,但是 无法确定如何访问中的会话变量 存储库

    如果向会话添加依赖项,则可能需要将其隔离,例如

    public class DropDownDataRepository : IDropDownDataRepository, IDisposable
    {
        // ... other fields
    
        private ISession session;
    
        public DropDownDataRepository(ISession session)
        {
            this.session = session;
        }
    
        public HttpResponseMessage MyList()
        {
             var myUserName = this.session.UserName;
             // ... etc
    
    ISession是这样的:

     public interface ISession
     {
          string UserName { get; }
     }
    
    实施方式如下:

     public class MySession : ISession
     {
         public string UserName
         {
             get
             {
                // potentially do some validation and return a sensible default if not present in session
                return HttpContext.Current.Session["UserName"].ToString();
             }
         }
    
     }
    
    当然,如果需要,可以将这个
    MySession
    类与
    HttpContext
    解耦


    关于这一点:

        //(This should be separated somehow, right?) 
        //Create a new instance of the Utility class
        Utility utility = new Utility();
    
    是的,每当您创建一个新的
    对象时,您都会将它们紧密地耦合在一起,这会给您带来问题,例如,如果您尝试单独对其进行单元测试

    在本例中,您可以从
    实用程序
    中提取
    i实用程序
    接口:

    public class Utility : IUtility
    {
        string GetWindowsUser();
    }
    
    然后:

    然后,您已经删除了
    实用工具
    DropDownDataRepository
    之间的依赖关系,并且可以轻松地替换为其他类型或模拟

    我的一个想法是在另一个页面中设置一个会话变量 使用另一个(模拟的)用户名,然后检查该会话 变量在获取实际用户名之前首先存在,但是 无法确定如何访问中的会话变量 存储库

    如果向会话添加依赖项,则可能需要将其隔离,例如

    public class DropDownDataRepository : IDropDownDataRepository, IDisposable
    {
        // ... other fields
    
        private ISession session;
    
        public DropDownDataRepository(ISession session)
        {
            this.session = session;
        }
    
        public HttpResponseMessage MyList()
        {
             var myUserName = this.session.UserName;
             // ... etc
    
    ISession是这样的:

     public interface ISession
     {
          string UserName { get; }
     }
    
    实施方式如下:

     public class MySession : ISession
     {
         public string UserName
         {
             get
             {
                // potentially do some validation and return a sensible default if not present in session
                return HttpContext.Current.Session["UserName"].ToString();
             }
         }
    
     }
    
    当然,如果需要,可以将这个
    MySession
    类与
    HttpContext
    解耦


    关于这一点:

        //(This should be separated somehow, right?) 
        //Create a new instance of the Utility class
        Utility utility = new Utility();
    
    是的,每当您创建一个新的
    对象时,您都会将它们紧密地耦合在一起,这会给您带来问题,例如,如果您尝试单独对其进行单元测试

    在本例中,您可以从
    实用程序
    中提取
    i实用程序
    接口:

    public class Utility : IUtility
    {
        string GetWindowsUser();
    }
    
    然后:


    然后,您已经消除了
    实用程序
    DropDownDataRepository
    之间的依赖关系,可以轻松地替换为另一种类型或模拟。

    我从Nikolai和Brent那里得到了很多帮助,并通过他们发布的答案获得了大部分结果,但最终我自己找到了完整的答案。我遇到的问题与无法访问WebAPI中的会话变量有关。因此,我确信有更干净的解决方案,但我确实改进了我的现有内容,并提出了以下代码,这是可行的

    需要此答案才能访问Web Api中的会话变量-

    GLOBAL.asax.cs

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            UnityConfig.RegisterComponents();
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    
        //Added to allow use of session state in Web API
        protected void Application_PostAuthorizeRequest()
        {
            if (IsWebApiRequest())
            {
                HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
            }
        }
    
        //Added to allow use of session state in Web API
        private bool IsWebApiRequest()
        {
            return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(WebApiConfig.UrlPrefixRelative);
        }
    
        protected void Session_Start(Object sender, EventArgs e)
        {
            //Default set the session variable to none
            Session["_impersonatedUser"] = "none";
        }
    
        protected void Session_End(Object sender, EventArgs e)
        {
            //Reset the session variable to blank
            Session["_impersonatedUser"] = "";
        }
    }
    
    UNITY.config

    public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();
    
            // register all your components with the container here
            // it is NOT necessary to register your controllers
    
            // e.g. container.RegisterType<ITestService, TestService>();
    
    
            container.RegisterType<IDropDownDataRepository, DropDownDataRepository>();
            container.RegisterType<IUtilityRepository, UtilityRepository>();
            container.RegisterType<ISessionRepository, SessionRepository>();
    
            //MVC5
            //Unity.MVC5 NuGet Package
            DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
    
            //WEB API 
            //Unity.WebApi NuGet Package
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
    }
    
    下拉数据存储库

    public class DropDownDataRepository : IDropDownDataRepository, IDisposable
    {
        private DatabaseEntities db = new DatabaseEntities();
        private IUtilityRepository _utilityRepository;
        private ISessionRepository _sessionRepository;
    
        //Dependency Injection of Utility and Session
        public DropDownDataRepository(IUtilityRepository utilityRepository, ISessionRepository sessionRepository)
        {
            _utilityRepository = utilityRepository;
            _sessionRepository = sessionRepository;
        }
    
        //Changed to a list here
        public List<MyProcedure> MyList()
        {
            string windowsUser;
            //Check the session variable to see if a user is being impersonated
            string impersonatedUser = _sessionRepository.ImpersonatedUser;
    
            //Grab the windowsUser from the Utility Repository
            windowsUser = _utilityRepository.GetWindowsUser();
    
            if (impersonatedUser != "none")
            {
                windowsUser = impersonatedUser;
            }        
    
            //Pass windowsUser parameter to the procedure
            var sourceQuery = (from p in db.MyProcedure(windowsUser)
                               select p).ToList();
    
            return sourceQuery;            
        }
    
        private bool disposed = false;
    
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    db.Dispose();
                }
            }
            this.disposed = true;
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
    
    public class UtilityRepository : IUtilityRepository
    {
        public string GetWindowsUser()
        {
            //Get the current windows user
            string windowsUser = HttpContext.Current.User.Identity.Name;
    
            return windowsUser;
        }
    }
    
     public class SessionRepository : ISessionRepository
    {
        public string ImpersonatedUser
        {
            get
            {
                return HttpContext.Current.Session["_impersonatedUser"].ToString();
            }
        }
    }
    
    实用程序界面

    public interface IDropDownDataRepository : IDisposable
    {
        HttpResponseMessage MyList();        
    }
    
    public interface IDropDownDataRepository : IDisposable
    {
        //Changed to list here
        List<MyProcedure> MyList();
    }
    
    public interface IUtilityRepository
    {
        string GetWindowsUser();
    }
    
    public interface ISessionRepository
    {
        string ImpersonatedUser { get; }
    }
    
    会话存储库

    public class DropDownDataRepository : IDropDownDataRepository, IDisposable
    {
        private DatabaseEntities db = new DatabaseEntities();
        private IUtilityRepository _utilityRepository;
        private ISessionRepository _sessionRepository;
    
        //Dependency Injection of Utility and Session
        public DropDownDataRepository(IUtilityRepository utilityRepository, ISessionRepository sessionRepository)
        {
            _utilityRepository = utilityRepository;
            _sessionRepository = sessionRepository;
        }
    
        //Changed to a list here
        public List<MyProcedure> MyList()
        {
            string windowsUser;
            //Check the session variable to see if a user is being impersonated
            string impersonatedUser = _sessionRepository.ImpersonatedUser;
    
            //Grab the windowsUser from the Utility Repository
            windowsUser = _utilityRepository.GetWindowsUser();
    
            if (impersonatedUser != "none")
            {
                windowsUser = impersonatedUser;
            }        
    
            //Pass windowsUser parameter to the procedure
            var sourceQuery = (from p in db.MyProcedure(windowsUser)
                               select p).ToList();
    
            return sourceQuery;            
        }
    
        private bool disposed = false;
    
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    db.Dispose();
                }
            }
            this.disposed = true;
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
    
    public class UtilityRepository : IUtilityRepository
    {
        public string GetWindowsUser()
        {
            //Get the current windows user
            string windowsUser = HttpContext.Current.User.Identity.Name;
    
            return windowsUser;
        }
    }
    
     public class SessionRepository : ISessionRepository
    {
        public string ImpersonatedUser
        {
            get
            {
                return HttpContext.Current.Session["_impersonatedUser"].ToString();
            }
        }
    }
    
    会话界面

    public interface IDropDownDataRepository : IDisposable
    {
        HttpResponseMessage MyList();        
    }
    
    public interface IDropDownDataRepository : IDisposable
    {
        //Changed to list here
        List<MyProcedure> MyList();
    }
    
    public interface IUtilityRepository
    {
        string GetWindowsUser();
    }
    
    public interface ISessionRepository
    {
        string ImpersonatedUser { get; }
    }
    

    我从尼古拉和布伦特那里得到了很多帮助,并且大部分时间都是通过他们发布的答案实现的,但最终我自己找到了完整的答案。我遇到的问题与无法访问WebAPI中的会话变量有关。因此,我确信有更干净的解决方案,但我确实改进了我的现有内容,并提出了以下代码,这是可行的

    需要此答案才能访问Web Api中的会话变量-

    GLOBAL.asax.cs

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            UnityConfig.RegisterComponents();
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    
        //Added to allow use of session state in Web API
        protected void Application_PostAuthorizeRequest()
        {
            if (IsWebApiRequest())
            {
                HttpContext.Current.SetSessionStateBehavior(SessionStateBehavior.Required);
            }
        }
    
        //Added to allow use of session state in Web API
        private bool IsWebApiRequest()
        {
            return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.StartsWith(WebApiConfig.UrlPrefixRelative);
        }
    
        protected void Session_Start(Object sender, EventArgs e)
        {
            //Default set the session variable to none
            Session["_impersonatedUser"] = "none";
        }
    
        protected void Session_End(Object sender, EventArgs e)
        {
            //Reset the session variable to blank
            Session["_impersonatedUser"] = "";
        }
    }
    
    UNITY.config

    public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();
    
            // register all your components with the container here
            // it is NOT necessary to register your controllers
    
            // e.g. container.RegisterType<ITestService, TestService>();
    
    
            container.RegisterType<IDropDownDataRepository, DropDownDataRepository>();
            container.RegisterType<IUtilityRepository, UtilityRepository>();
            container.RegisterType<ISessionRepository, SessionRepository>();
    
            //MVC5
            //Unity.MVC5 NuGet Package
            DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
    
            //WEB API 
            //Unity.WebApi NuGet Package
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
    }
    
    下拉数据存储库

    public class DropDownDataRepository : IDropDownDataRepository, IDisposable
    {
        private DatabaseEntities db = new DatabaseEntities();
        private IUtilityRepository _utilityRepository;
        private ISessionRepository _sessionRepository;
    
        //Dependency Injection of Utility and Session
        public DropDownDataRepository(IUtilityRepository utilityRepository, ISessionRepository sessionRepository)
        {
            _utilityRepository = utilityRepository;
            _sessionRepository = sessionRepository;
        }
    
        //Changed to a list here
        public List<MyProcedure> MyList()
        {
            string windowsUser;
            //Check the session variable to see if a user is being impersonated
            string impersonatedUser = _sessionRepository.ImpersonatedUser;
    
            //Grab the windowsUser from the Utility Repository
            windowsUser = _utilityRepository.GetWindowsUser();
    
            if (impersonatedUser != "none")
            {
                windowsUser = impersonatedUser;
            }        
    
            //Pass windowsUser parameter to the procedure
            var sourceQuery = (from p in db.MyProcedure(windowsUser)
                               select p).ToList();
    
            return sourceQuery;            
        }
    
        private bool disposed = false;
    
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    db.Dispose();
                }
            }
            this.disposed = true;
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
    
    public class UtilityRepository : IUtilityRepository
    {
        public string GetWindowsUser()
        {
            //Get the current windows user
            string windowsUser = HttpContext.Current.User.Identity.Name;
    
            return windowsUser;
        }
    }
    
     public class SessionRepository : ISessionRepository
    {
        public string ImpersonatedUser
        {
            get
            {
                return HttpContext.Current.Session["_impersonatedUser"].ToString();
            }
        }
    }