MVC Controllers和Forms验证
想想下,一組從Forms驗證抽象出來的登入/登出Controllers行為特有的ActionResult實現。。
我已經使用ASP.NETMVC重新實現了我的個人網站(projects.nikhilk.net)的一部分。其中之一就是登入/登出功能的實現。當你創建一個新的ASP.NETMVC應用程序,默認的就會包含一個簡單的AccountController。這個Controller中包含了登入/登出,并實現了IFormsAuthentication接口。其默認實現基于System.Web.Security.FormsAuthentication APIs(SetAuthCookie and SignOut)。可以仿照給這個接口的實現以便用于United測試。
盡管如此,當我在自己的Controller中實現登入/登出時,我發現一個奇怪現象,行為(actions)直接的訪問FormsAuthentication(甚至是通過接口)。我以為行為應該簡單地完成用戶驗證,而后返回一個處理生成響應的匹配的ActionResult,這該實例中就是設置或清除cookie,并重定向Url。為此,我創建了FormsLoginResult和FormsLogoutResult。很明顯的他們是成對的出現的,but I thought I'd go ahead and share anyway。
首先,我將顯示AccountController中修改過的Login和Logout方法。
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Login(string username, string password, bool rememberMe) {...if (ViewData.ModelState.IsValid) {// Attempt to loginbool loginSuccessful = Provider.ValidateUser(username, password);if (loginSuccessful) {return new FormsLoginResult(username, rememberMe);}else {...}}// If we got this far, something failed, redisplay form...return View(); }public ActionResult Logout() {return new FormsLogoutResult(); }現在Login和Logout行為不再和authentication是否通過cookie跟蹤以及需要重定位到哪里(默認主頁、參數關聯的url等)相關聯。
其次、建立這兩個函數的測試單元。我使用Moq實現測試需要的MembershipProvider的模擬,當是不再需要IFormsAuthentication的實現。
[TestClass] public class AccountControllerTest {[TestMethod]public void LoginSuccessful() {string testUserName = "TestUser";string testPassword = "TestPassword";Mock<MembershipProvider> mockMembership = new Mock<MembershipProvider>();mockMembership.Expect<bool>(m => m.ValidateUser(testUserName, testPassword)).Returns(true).AtMostOnce().Verifiable();AccountController controller = new AccountController(mockMembership.Object);ActionResult result = controller.Login(testUserName, testPassword, false);Assert.IsInstanceOfType(result, typeof(FormsLoginResult));FormsLoginResult loginResult = (FormsLoginResult)result;Assert.AreEqual<string>(loginResult.UserName, testUserName);Assert.AreEqual<bool>(loginResult.PersistentCookie, false);}[TestMethod]public void LoginFailure() {string testUserName = "TestUser";string testPassword = "TestPassword";Mock<MembershipProvider> mockMembership = new Mock<MembershipProvider>();mockMembership.Expect<bool>(m => m.ValidateUser(testUserName, testPassword)).Returns(true).AtMostOnce().Verifiable();AccountController controller = new AccountController(mockMembership.Object);ActionResult result = controller.Login(testUserName, "badPassword", false);Assert.IsInstanceOfType(result, typeof(ViewResult));} }下面是FormsLoginResult 和FormsLogoutResult的實現。這里使用了MVC提供的構建自定義action results可擴展性較好的實現。
public class FormsLoginResult : ActionResult {private string _userName;private string _userData;private bool _persistentCookie;public FormsLoginResult(string userName): this(userName, /* persistentCookie */ false) {}public FormsLoginResult(string userName, bool persistentCookie) {if (String.IsNullOrEmpty(userName)) {throw new ArgumentNullException("userName");}_userName = userName;_persistentCookie = persistentCookie;}public bool PersistentCookie {get { return _persistentCookie; }}public string UserData {get { return _userData; }set { _userData = value; }}public string UserName {get { return _userName; }}public override void ExecuteResult(ControllerContext context) {HttpResponseBase response = context.HttpContext.Response;if (String.IsNullOrEmpty(_userData)) {FormsAuthentication.SetAuthCookie(_userName, _persistentCookie);}else {FormsAuthenticationTicket ticket =new FormsAuthenticationTicket(1, _userName,DateTime.Now, DateTime.Now.AddMinutes(30),_persistentCookie,_userData, FormsAuthentication.FormsCookiePath);string encryptedTicket = FormsAuthentication.Encrypt(ticket);HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,encryptedTicket);cookie.HttpOnly = true;cookie.Secure = FormsAuthentication.RequireSSL;cookie.Path = FormsAuthentication.FormsCookiePath;if (FormsAuthentication.CookieDomain != null) {cookie.Domain = FormsAuthentication.CookieDomain;}response.Cookies.Add(cookie);}response.Redirect(FormsAuthentication.GetRedirectUrl(_userName, _persistentCookie));} }令人慶幸的是,FormsLoginResult同樣的在FormsAuth cookie內封裝了一些自定義用戶數據,這些數據可以通過HttpApplication的Authenticate事件獲取,并可以使用FormsAuthentication.Decrypt將AuthCookie內數據轉換為一個FormsAuthenticationTicket實例,以及從Ticket中獲取的用戶數據。我在我的網站中使用這個跟蹤一些元數據以便于在Requests后重新創建代理實例。
第二個action result FormsLogoutResult非常簡單。
?
public class FormsLogoutResult : ActionResult {private string _url;public FormsLogoutResult(): this(FormsAuthentication.DefaultUrl) {}public FormsLogoutResult(string url) {if (String.IsNullOrEmpty(url)) {throw new ArgumentNullException("url");}_url = url;}public string Url {get { return _url; }}public override void ExecuteResult(ControllerContext context) {FormsAuthentication.SignOut();context.HttpContext.Response.Redirect(_url);} }源:http://www.nikhilk.net/Default.aspx轉載于:https://www.cnblogs.com/Silicon-Fado/archive/2009/03/15/1412198.html
總結
以上是生活随笔為你收集整理的MVC Controllers和Forms验证的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS实现的展开隐藏效果
- 下一篇: Dynamips和Vmware完成CCV