从数据层访问 HttpContext 和 User Identity

Accessing HttpContext and User Identity from data layer

我需要在我的基础实体上实现 AddedBy/ChangedBy 类型字段,所有其他实体都继承自该类型字段 (Fluent Nhibernate)。

从我的 Repository/Data 层访问 HttpContext.User.Identity 可能不是一个好主意..或者是吗? 获取我的用户(当前身份)信息以记录记录是由谁添加或更改的最佳方式是什么? 重构整个应用程序以在存储库调用中包含用户信息将是愚蠢的。我确信有更好、更通用的方法。

AddedBy/ChangedBy 字段在任何数据后端中都可能很重要。您甚至可能希望使用 AccessedBy 进行日志记录。因此,您会认为用户信息是数据的核心部分。出于安全原因,您也可能希望记录其他详细信息,例如客户端的 IP 地址。将整个上下文波及到数据层可能是个好主意,这样您就可以灵活地捕获和保存客户信息。

你是对的。从您的存储库中引用您的 HttpContext.User.Identity class 不是一个好主意。 HttpContext 是一个 UI 问题,因此,不应超出 UI 层。

您应该做的是利用 IoC 容器(例如 StructureMap)将您的依赖项(HttpContext.User.Identity)详细信息注入您的存储库,或通过依赖项注入的任何其他层(例如服务层)。

有关如何设置的示例(在本例中为会话对象),请参阅 this answer 的后半部分。

HttpContext.Current 是一个静态成员,您可以在应用程序的任何位置访问它。 https://msdn.microsoft.com/en-us/library/system.web.httpcontext.current%28v=vs.110%29.aspx 显然是有问题的,比如调用代码时如果没有HttpContext

所以HttpContext.Current。用户应该为你工作。我不推荐它,因为你的底层数据访问代码现在取决于应该保留在你的显示或控制器逻辑等中的东西。此外,这假设你的数据访问是在网络应用程序本身而不是一部分,比如,一个外部图书馆。

就我个人而言,作为添加和修改数据库调用的一部分,我只是传递重要的详细信息,例如用户 ID 和访问时间。做一个 "AuditTrail" class 什么的。这将使您可以在另一个项目中重用该数据访问代码(总是一件好事),而不必取出所有 HttpContext 东西。

从数据层访问 HttpContext 使生活变得更加艰难,特别是如果您使用单元测试。解决方案是创建一个服务来提供应用程序范围内的用户信息,例如:

public interface ICurrentUserService {
   string UserName {get;}
   string UserId {get;}
   string HostIP {get;}
   // etc.
}

然后你可以实现具体的服务并使用你的注入 首选 IoC 容器。

public class CurrentWebUserService : ICurrentUserService {
    // implement interface members 
    public CurrentWebUserService(HttpContext context) { ... }

    public string UserName { get { ... } } 
    // etc.
}

// maybe you want a stub service to inject while unit testing.
public class CurrentUserServiceStub : ICurrentUserService {

}

// data layer
public class MyDaoService {
    public DaoService(ICurrentUserService currentUser) { ... }
}

无论是否使用 "CurrentUser",我都使用工厂来获取正确的回购协议,因为有时您需要知道用户是谁,有时则不需要。

//I have a current user that I got from the Identity
var repo = RepoFactory.GetRepo<Users>(currentUserId);

//I don't have a current user
var repo = RepoFactory.GetRepo<Users>()

这样您就可以从 HttpContext 中提取身份并仅将您需要的详细信息传递给存储库。

  1. HttpContext.User.IdentitySystem.Security.Principal.IIdentity 类型。不要把它与 Microsoft.AspNet.Identity 库(NuGet 包)搞混,它实际上由 asp.net-identity 标记指向你的问题。

  2. 身份库由公共部分及其 ORM 实现组成。通常是 Entity Framework。但是如果您要按照您在 NHibernate 中描述的方式使用 Microsoft.AspNet.Identity 包,那么您很可能需要 this package

我没用过,但是用了EF实现。请参阅 this answer 如何继承预定义 IdentityDbContext<T>,其中 T 是您的用户 class。我想,NH 也有类似的流畅配置。然后你可以 link 你 DbContextAppUser

中的任何实体