我正在开发一个 Asp.net (MVC,但这并不重要)应用程序。 我有一个自定义 IHttpModule 负责 PostAuthenticateRequest 更改用户主体和 身份。
当用户登录时,我将 UserID 和 UserName 存储在身份验证 cookie 中。 我有一个 IUser(由 DAO 和业务对象层实现,每个层都有自己的附加成员),我在整个业务服务类中都需要它。 当用户想要任何东西时,我必须提供 IUser 对象实例(通常来自业务对象层),因此从身份验证票证中提供 ID 是不够的。
所以我正在考虑如何以及在哪里最好地保留登录用户的 IUser 数据?
- 我不想每次都从数据库中获取它(基于身份验证票证的 UserID 数据),
- 我无法将其存储在 Session 中,因为我必须在 PostAuthenticateRequest 中工作,而 Session 尚未准备好,
- 我希望所有功能都可以封装在
我看到的自定义 IHttpModule 选择中:
- 缓存
- Cookie
- (会话) - 通过从 PostAuthenticateRequest 移动到 PostAcquireRequestState 事件并更改那里的主体/身份,但我想避免这个
似乎使事情复杂化的过程是:
- 用户日志-在,用户数据从数据库中获取并以某种方式持久保存以供以后的请求
- 用户注销,用户数据必须自动从持久介质中删除
- 数据库的请求时重新读取
用户更改自己的配置文件,用户数据必须被丢弃并在下一个来自 不希望所有这些都由 HttpModule 自动处理(如果可能的话),以消除开发人员忘记重置这些内容的错误。
我也不想要的是写入/读取一些硬编码变量/键并在应用程序的其他部分中操作它们。 这只会带来技术债务。
问题
- 您有什么建议?
- SO 如何在请求之间保留用户数据?
I'm developing an Asp.net (MVC but this doesn't really matter) application. I have a custom IHttpModule that's responsible for the PostAuthenticateRequest to change user principal & identity.
I'm storing UserID and UserName in authentication cookie when user logs-in. I have an IUser (implemented by DAO and Business Objects layer, each with their own additional members) that I need all over Business Service classes. When a user wants anything I have to provide IUser object instance (usually from Business Objects layer) so providing ID from the auth ticket isn't sufficient.
So I'm thinking of how and where would be best to persist logged in user's IUser data?
- I don't want to fetch it every time from the DB (based on authentication ticket's UserID data)
- I can't store it in Session since I have to work inside PostAuthenticateRequest, where Session isn't ready yet
- I want all the functionality to be encapsulated within my custom IHttpModule
Choices that I see:
- Cache
- Cookie
- (Session) - by moving from PostAuthenticateRequest to PostAcquireRequestState event and change principal/identity there, but I'd like to avoid this
Processes that seem to complicate things are:
- User logs-in, user data is fetched from the DB and persisted somehow for later requests
- User logs-out, user data has to be removed from persisted medium automagically
- User changes own profile, user data has to be discarded and reread on next request from the DB
I wan't all these to be handled automatically by HttpModule (if possible) to eliminate developer's errors of forgetting to reset these things.
What I also don't want is to write/read some hardcoded variables/keys and manipulate them in other parts of the application. This would only present technical debt.
Questions
- What would you suggest?
- How does SO persist user data between requests?
发布评论
评论(1)
根据您的要求,我认为最好的解决方案是从 cookie 中检索 ID 并使用它来索引 Http 缓存 (HttpContext.Current.Cache)。
如果您想维护用户访问它的方式,请将缓存包装在“UserCache”对象中。 该对象可以由 HttpModule 构建,并作为(等待它...)单例存储在缓存本身中,或者更好的是,在需要从 http 缓存中提取时构建。 这取决于您需要在哪里访问它以及 HttpContext.Current.Cache 是否直接可用。 惰性实现如下。
再次强调,这是为了清楚起见,并不是我实际实现它的方式。
使用默认的缓存机制(或者更好的是 DI 提供的缓存机制,这样您就不必依赖于实现),您可以设置过期时间以自动从缓存中删除用户,如评论中所述。 您可以将缓存设置为依赖于 SQL Server 更新来处理更新,或者将其作为服务的一部分手动更新以保存更改。
有关默认缓存的更多信息,请访问此处。 有关缓存依赖项的更多信息,请参阅< a href="http://msdn.microsoft.com/en-us/library/system.web.caching.cachedependency.aspx" rel="nofollow noreferrer">此处。
在 HttpModule 本身中,我想您可以在 EndRequest 事件中做一些魔术来查看请求是否经过身份验证,然后根据 cookie 将用户注销,但我不确定这是否有效,因为我从未尝试过它。 您可能想查看 MSDN 上的这篇文章从 1.1 天前开始,看看它是否能解决您想要解决的一些问题。
至于 SO 架构以及他们如何做到这一点,我想他们会在需要时加载它,因为他们始终将大部分数据库保存在 RAM 中(http://highscalability.com/stack-overflow-architecture)。
Given your requirements, I suppose the best solution is to retrieve the ID from the cookie and use it to index into the Http Cache (HttpContext.Current.Cache).
If you want to maintain how users access it, wrap the Cache in a "UserCache" object. The object could be constructed by an HttpModule and stored as a (wait for it...) singleton within the cache itself or, better yet, just constructed when needed to pull from the http cache. This would depend on where you need to access it and whether HttpContext.Current.Cache is directly available. The lazy implementation is below.
Again, this is for clarity and is not how I'd actually implement it.
Using the default caching mechanisms (or better yet a caching mechanism supplied by DI so you're not tied to an implementation), you can set an expiration to automatically remove users from the cache as mentioned in the comment. You can setup the cache to be dependent on SQL server updates as well to handle the updates or manually update it as part of the service to save changes.
More information about the default cache is available here. More information about cache dependencies is available here.
In the HttpModule itself, I suppose you could do some magic in the EndRequest event to see if the request is authenticated and then log the user out based on the cookie, but I'm not sure if that would work as I've never tried it. You might want to have a look at this article on MSDN from WAY back in the 1.1 days and see if it answers some of the problems you are trying to solve.
As for the SO architecture and how they do it, I'd imagine they load it when needed because they keep most of the database in RAM at all times (http://highscalability.com/stack-overflow-architecture).