May*_*ayo 3 authentication asp.net-mvc inversion-of-control principal
我希望能够访问经过身份验证的用户(如UserId和FirstName)的自定义属性,而无需每次都查询数据库.我通过Stack Overflow上的帖子找到了这个网站,我喜欢这种方法 - 但我使用IoC /存储库并决定不尝试使用global.asax与数据库进行通信,因为它担心它与存储库模式不兼容.
相反,我创建了一个CustomPrincipal接口,我使用IoC(Castle)创建一个实例并将其传递给控制器(以及随后传递给我的基本控制器).
基本控制器使用我在CustomPrincipal中创建的方法来实现博客作者在global.asax中处理的相同任务.即,CustomPrincipal从数据库或缓存初始化并分配给HttpContext.Current.User.
我的控制器/视图然后可以引用属性如下...
((ICustomPrincipal)(HttpContext.Current.User)).FirstName;
Run Code Online (Sandbox Code Playgroud)
它有效,但我感觉到一些代码味道.首先,如果我从控制器引用HttpContext,我已经杀死了我的单元测试.我正在考虑修改我的CustomPrincipal对象以返回上面的值(这样我可以在我的单元测试中模拟它)但我想知道这是否是一个解决方法而不是一个好的解决方案.
我是以正确的方式来做这件事的吗?我是否可以做一些小的调整以使其成为一个强大的解决方案,或者我应该从头开始使用FormsAuthenticationTicket或其他类似的东西?
谢谢!
我想抛弃另一种想法,以便寻找这些信息的人可以有一些选择.
我去寻找一个可行的FormsAuthenticationTicket示例,发现NerdDinner在添加自定义属性的同时做了相当不错的工作而不会影响单元测试.
在我的例子中,我修改了我的LogOn例程(我在单元测试中已经嘲笑)来创建FormsAuthenticationTicket.NerdDinner加密票证并将其添加为cookie,但我也可以像原始提案一样将加密票证添加到缓存中.我还用表示所有自定义属性的JSON序列化对象替换了单个UserData属性.
CustomIdentityDTO dto = new CustomIdentityDTO {
UserId = userId, FirstName = firstName, LastName = lastName };
JavaScriptSerializer serializer = new JavaScriptSerializer();
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1, // version
username,
DateTime.Now, // creation
DateTime.Now.AddMinutes(30), // expiration
false, // not persistent
serializer.Serialize(dto));
string encTicket = FormsAuthentication.Encrypt(authTicket);
//HttpContext.Current.Response.Cookies.Add(...)
HttpContext.Current.Cache.Add(username, encTicket, ...
Run Code Online (Sandbox Code Playgroud)
然后我通过PostAuthenticateRequest处理程序检索global.asax中的加密票证(来自缓存或cookie),就像NerdDinner(用于cookie)或博主的提议(用于缓存).
NerdDinner实现了IIdentity而不是IPrincipal.对代码中自定义字段的引用如下:
((CustomIdentity)Page.User.Identity).FirstName // from partial view
((CustomIdentity)User.Identity).FirstName // from controller
Run Code Online (Sandbox Code Playgroud)
使用这两种方法后,我发现NerdDinner的方法非常有效.切换后我没有遇到太多障碍物.
| 归档时间: |
|
| 查看次数: |
3838 次 |
| 最近记录: |