想想下,一组从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验证相关推荐

  1. ASP.NET MVC 实现统一登录验证

    1.先写个主页面 using System; using System.Collections.Generic; using System.Linq; using System.Web; using ...

  2. 就是这么简单(续)!使用 RestAssuredMockMvc 测试 Spring MVC Controllers(转)

    接我前面一篇文章关于RestAssured测试Restful web service的, RestAssured还有一个功能, 使用RestAssuredMockMvc 单元测试你的Spring MV ...

  3. 使用Spring 3 MVC处理表单验证

    本文是有关Spring 3的系列文章的一部分.该系列的早期文章是使用Spring 3 MVC的Hello World和使用Spring 3 MVC的 Handling Forms . 现在让我们更深入 ...

  4. ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)

    ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证,在默认的情况下,基于ValidationAttribute的声明是验证被使用,我们只需要将相应的ValidationAttri ...

  5. Asp.net中基于Forms验证的角色验证授权[转]

    Asp.net的身份验证有有三种,分别是"Windows | Forms | Passport",其中又以Forms验证用的最多,也最灵活. Forms 验证方式对基于用户的验证授 ...

  6. MVC中的统一验证机制~续

    前段时间我发表的关于MVC架构中对验证方式的设计,收到了不少朋友的留言,意思是说过于复杂,复用性不高,当然我的出发点是减少实体部门的代码量. 最近在朋友的建议下,看了另一种验证方式,事实上就是MVC实 ...

  7. Nancy之Forms验证

    授权几乎是所以系统都不可或缺的部分,在Nancy中怎么授权呢?我们这篇博文来说一下Nancy的Forms授权. 首先在NuGet上安装Nancy.Authentication.Forms Nancy的 ...

  8. ASP.NET MVC 4 (十) 模型验证

    模型验证是在模型绑定时检查从HTTP请求接收的数据是否合规以保证数据的有效性,在收到无效数据时给出提示帮助用户纠正错误的数据. 显式模型验证 验证数据最直接的方式就是在action方法中对接收的数据验 ...

  9. 浅谈ASP.NET Forms验证

    ASP.NET Forms验证 用户验证是每一个项目必须的一个模块,由于已经很久没有碰到这一块内容,今天写一个用户验证居然脑子一片空白.于是乎就和一个同事进行了一片讨论,晚上回家决定把讨论的结果给记录 ...

最新文章

  1. XenServer和VMware vSphere技术比较
  2. GRE OVER IPSEC
  3. C++ Primer 5th笔记(chap 19 特殊工具与技术)定位 new 表达式
  4. 插入,选择,归并,快速排序
  5. C# WinForm开发系列 - DataGridView
  6. maven项目概念模型图
  7. 如何用计算机做出折线图,曲线图怎么做-怎样在电脑上做曲线图电脑上如何做曲线图 – 手机爱问...
  8. Atitit 软件项目非法模块与功能的管理与  监狱管理的对比 原理与概论attilax总结
  9. paip.c#.net 多线程调用控件的问题
  10. c语言实现 网络嗅探程序代码,C语言实现网络嗅探器
  11. 利用随机矩阵理论(random matrix theory)确定微生物网络构建阈值
  12. BLE 技术(四)--- 链路层五种通信模式和空口协议设计 (Core_v5.2)
  13. Python练习题答案: 纳特拼音alaphabeta【难度:1级】--景越Python编程实例训练营,1000道上机题等你来挑战
  14. docker服务假死解决方案
  15. 搭建Cacti监控(2)
  16. (附源码)mysql+ssm学生选课系统 毕业设计 170920
  17. Mac安装指定版本的node
  18. Mac系统Safari浏览器快捷键大全
  19. arm_neon.h文件ABI说明
  20. NRC 0x78 在CAPL中如何打开和关闭

热门文章

  1. 最长回文子串的不同解法
  2. java多线程 -- 同步鎖
  3. jQuery之each()的使用与实现
  4. 从头开始敲代码之《从BaseApplication/Activity开始(二)》
  5. bootstrat 设置 select option 选项的值
  6. 使用ADOMD.NET获取Analysis Services元数据
  7. flink sql实现interval join的图解
  8. npm/cnpm install是啥意思
  9. 第4章-机器学习基础
  10. Unknown column 'XXX' in 'where clause'一例排查