在ASP.NET MVC中的自定义主 [英] Custom principal in ASP.NET MVC
问题描述
我希望能够访问的定制属性像用户名和姓身份验证的用户无需每次都查询数据库。我发现<一个href=\"http://webcache.googleusercontent.com/search?q=cache%3aHKMtchbXHEAJ%3ablog.$c$cvelop.dk/post/2007/11/24/ASPNET-20-Forms-authentication-Keeping-it-customized-yet-simple.aspx+FormsIdentity+principal+httpcontext+unit+testing&cd=23&hl=en&ct=clnk&gl=us\"相对=nofollow>本网站通过堆栈溢出后和我一样的做法 - 但我使用的IoC /存储库,并决定不尝试并获得的Global.asax生怕与数据库进行通信,它会与库模式不兼容。
I want to be able to access custom properties for an authenticated user like UserId and FirstName without querying the database each time. I found this site through a post on Stack Overflow and I like the approach - but I use IoC / repositories and decided not to try and get global.asax to communicate with the database for fear that it would be incompatible with the repository pattern.
相反,我创建CustomPrincipal一个接口,我使用的IoC(城堡)创建一个实例,并把它传递给控制器(随后我的基本控制器)。
Instead, I created an interface to CustomPrincipal and I use IoC (Castle) to create an instance and pass it to the controllers (and subsequently to my base controller).
该基地控制器使用我CustomPrincipal创建实现该博客作者在Global.asax中处理同一任务的方法。即,CustomPrincipal从数据库或高速缓存初始化,并分配给HttpContext.Current.User
The base controller uses methods I created in CustomPrincipal to achieve the same task that the blog author addressed in global.asax. Namely, CustomPrincipal is initialized from the database or cache and assigned to HttpContext.Current.User.
我的控制器/视图可以然后引用属性如下...
My controllers/views can then reference the properties as follows...
((ICustomPrincipal)(HttpContext.Current.User)).FirstName;
它的工作原理,但我感应有些code气味。首先,如果我引用的HttpContext从控制器我杀了我的单元测试。我在想修改我CustomPrincipal对象返回上述值(这样我可以在我的单元测试嘲笑吧),但我想如果这是不是一个很好的解决方案一种解决方法。
It works, but I'm sensing some code smells. First and foremost, if I reference HttpContext from the controllers I've killed my unit testing. I'm thinking about modifying my CustomPrincipal object to return the above value (such that I can mock it in my unit tests) but I'm wondering if this is a workaround as opposed to a good solution.
我要对这个正确的方式?是否有小的调整,我可以做,使之成为强大的解决方案或我应该从从头开始的FormsAuthenticationTicket或东西开始这种效果?
Am I going about this the right way? Are there minor tweaks I could do to make it a robust solution or should I start from scratch with FormsAuthenticationTicket or something to that effect?
谢谢!
推荐答案
我想抛出一个替代的想法只是让人们寻找这些信息可以有一些选择。
I wanted to throw out an alternative idea just so people looking for this information can have some choices.
我去寻找一个可行的FormsAuthenticationTicket的例子,发现的NerdDinner 做了pretty体面的工作,加入自定义属性,而不会影响单位测试。
I went searching for a viable FormsAuthenticationTicket example and found that NerdDinner does a pretty decent job adding custom properties without impacting unit testing.
在我的情况,我修改了登录程序(我已经在我的单元测试嘲讽)创建的FormsAuthenticationTicket。的NerdDinner加密票证并将它作为一个cookie,但我还能够添加加密票证缓存像<一个href=\"http://webcache.googleusercontent.com/search?q=cache%3aHKMtchbXHEAJ%3ablog.$c$cvelop.dk/post/2007/11/24/ASPNET-20-Forms-authentication-Keeping-it-customized-yet-simple.aspx+FormsIdentity+principal+httpcontext+unit+testing&cd=23&hl=en&ct=clnk&gl=us\">original建议。我也取代了单一的UserData属性用JSON序列化对象重新presenting我所有的自定义属性。
In my case, I modified my LogOn routine (which I was already mocking in my unit tests) to create a FormsAuthenticationTicket. NerdDinner encrypts the ticket and adds it as a cookie, but I am also able to add the encrypted ticket to cache like the original proposal. I also replaced the single UserData property with a JSON serialized object representing all of my custom properties.
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, ...
然后我检索加密票证(无论是从缓存或Cookie)通过PostAuthenticateRequest处理程序很像的NerdDinner在Global.asax中(用于饼干)或博客的建议(高速缓存)。
Then I retrieve the encrypted ticket (either from cache or cookies) in global.asax through a PostAuthenticateRequest handler much like NerdDinner (for cookie) or the blogger's proposal (for cache).
的NerdDinner实现的IIdentity而不是IPrincipal的。是参考在code中的自定义字段如下:
NerdDinner implements IIdentity instead of IPrincipal. References to the custom fields in the code are as follows:
((CustomIdentity)Page.User.Identity).FirstName // from partial view
((CustomIdentity)User.Identity).FirstName // from controller
使用这两种方法工作后,我发现的NerdDinner的方法很好。切换后,我还没有障碍物的途中遇到了。
After working with both methods, I find that NerdDinner's approach works very well. After switching over I haven't encountered much in the way of obstacles.
这篇关于在ASP.NET MVC中的自定义主的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!