简体   繁体   English

从数据层访问 HttpContext 和 User Identity

[英]Accessing HttpContext and User Identity from data layer

I need to implement AddedBy/ChangedBy type fields on my Base Entity that all other entities inherit from ( Fluent Nhibernate ).我需要在所有其他实体继承自 (Fluent Nhibernate) 的基础实体上实现AddedBy/ChangedBy 类型字段。

Accessing HttpContext.User.Identity from within my Repository/Data layer is probably not a good idea.. or is it ?从我的 Repository/Data 层访问HttpContext.User.Identity可能不是一个好主意......或者是吗? What's the best way to grab my user ( current identity ) information to record who the records were added or changed by ?获取我的用户(当前身份)信息以记录谁添加或更改了记录的最佳方法是什么? Re-factoring the entire application to include user information in repository calls would be silly.重构整个应用程序以在存储库调用中包含用户信息是愚蠢的。 I'm sure there is a better, more generic way.我相信有更好、更通用的方法。

Access the HttpContext from the Data Layer makes the life harder, specially if you use Unit Tests.从数据层访问 HttpContext 会使事情变得更加困难,特别是如果您使用单元测试。 The solution is to create a service to provide application wide user information, something like:解决方案是创建一个服务来提供应用程序范围的用户信息,例如:

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

Then you can implement the concrete service and inject it using your preferred IoC container.然后你可以实现具体的服务并使用你喜欢的 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) { ... }
}

You're correct.你是对的。 Referencing your HttpContext.User.Identity class from within your repository is not a good idea.从存储库中引用HttpContext.User.Identity类不是一个好主意。 The HttpContext is a UI concern and as such, should go no further than the UI layer. HttpContext是一个 UI 问题,因此,不应比 UI 层更进一步。

What you should be doing is harnessing an IoC container (such as StructureMap) to inject your dependency ( HttpContext.User.Identity ) details into your repository, or any other layer such as the service layer via dependency injection.您应该做的是利用 IoC 容器(例如 StructureMap)将您的依赖项( HttpContext.User.Identity )详细信息注入您的存储库或任何其他层,例如通过依赖项注入的服务层。

For an example of how this can be setup (in this instance it's the session object) see the latter part of this answer .有关如何设置它的示例(在本例中它是会话对象),请参阅此答案的后半部分。

HttpContext.Current is a static member that you can access anywhere in the application. HttpContext.Current 是一个静态成员,您可以在应用程序的任何地方访问它。 https://msdn.microsoft.com/en-us/library/system.web.httpcontext.current%28v=vs.110%29.aspx Obviously there are problems, such as if you don't HAVE an HttpContext when the code is called. https://msdn.microsoft.com/en-us/library/system.web.httpcontext.current%28v=vs.110%29.aspx显然有问题,比如如果你没有 HttpContext 时代码被调用。

So HttpContext.Current.User should work for you.所以 HttpContext.Current.User 应该适合你。 I wouldn't recommend it, because your underlying data access code is now depending on stuff that should be kept to your display or controller logic, etc. Also, this assumes that your data access is in the web application itself and not part of, say, an external library.我不会推荐它,因为您的底层数据访问代码现在取决于应该保留在您的显示或控制器逻辑等中的内容。此外,这假设您的数据访问在 Web 应用程序本身中而不是其中的一部分,比如说,一个外部图书馆。

Personally, I'd just pass in the salient details, like user ID and access time, as part of the add and modify database calls.就我个人而言,作为添加和修改数据库调用的一部分,我只会传递重要的详细信息,例如用户 ID 和访问时间。 Make an "AuditTrail" class or something.制作“AuditTrail”类或其他东西。 That would let you reuse that data access code (always a good thing) in another project without having to pull out all the HttpContext stuff.这将使您可以在另一个项目中重用该数据访问代码(总是一件好事),而无需取出所有 HttpContext 内容。

The AddedBy/ChangedBy field is potentially important in any data backend. AddedBy/ChangedBy 字段在任何数据后端都可能很重要。 You may even want to have AccessedBy for logging purposes.您甚至可能希望将 AccessedBy 用于日志记录。 Therefore, you would want to think that the user information is a central part of your data.因此,您可能会认为用户信息是数据的核心部分。 It is also possible that you may want other details such as the client's IP address logged for security reasons.出于安全原因,您也可能希望记录其他详细信息,例如客户端的 IP 地址。 Probably a good idea to have the entire context rippled down to the data layer so that you have the flexibility to capture and save the client information.将整个上下文向下延伸到数据层可能是一个好主意,这样您就可以灵活地捕获和保存客户端信息。

I have used a factory to get the correct repo with or without a "CurrentUser" since sometimes you need to know who the user is and sometimes you don't.我已经使用工厂来获得正确的 repo,无论是否带有“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>()

This way you can pull the Identity from the HttpContext and pass only details you need to the repo.通过这种方式,您可以从 HttpContext 中提取身份并仅将您需要的详细信息传递给存储库。

  1. HttpContext.User.Identity is of System.Security.Principal.IIdentity type. HttpContext.User.IdentitySystem.Security.Principal.IIdentity类型。 Don't mess it up with Microsoft.AspNet.Identity library (NuGet package) which is actually pointed by asp.net-identity tag in your question.不要将它与Microsoft.AspNet.Identity库(NuGet 包)混淆,它实际上是由您的问题中的 asp.net-identity 标记指向的。

  2. Identity lib consists of common part and its ORM implementation.身份库由公共部分及其 ORM 实现组成。 Typically it is for Entity Framework .通常它用于Entity Framework But if you're going to use Microsoft.AspNet.Identity package in the way you describe with NHibernate, then you most likely will need this package .但是,如果您打算按照您在 NHibernate 中描述的方式使用Microsoft.AspNet.Identity包,那么您很可能需要这个包

I didn't use it, but I used EF implementation.我没有使用它,但我使用了EF实现。 See this answer how to inherit of predefined IdentityDbContext<T> where T is your User class.请参阅此答案如何继承预定义的IdentityDbContext<T>其中 T 是您的用户类。 I guess, NH has similar fluent configuration.我猜,NH 也有类似的流畅配置。 Then you can link any of entities in your DbContext to AppUser然后您可以将DbContext任何实体链接到AppUser

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM