Asp.Net MVC 身份验证-Forms

在MVC中对于需要登录才可以访问的页面,只需要在对应的Controller或Action上添加特性[Authorize]就可以限制非登录用户访问该页面。那么如果实现登录?

Form登录

应用程序确认用户状态

HTTP协议是无状态的。所以上一次请求和下一次请求并不能相互关联起来,就是说这些请求并不能确定是哪个用户和用户的状态。但是对于登录来说,我们就需要准确的知道用户的状态及是哪个用户。

通常有两种情况来记录用户状态。

  • 一种在服务端通过Session来标识。

  • 一种通过Cookie在客户端标识用户。(用户每次请求应用程序时都会携带该Cookie。)

Form登录实现

Forms 身份验证将身份验证标记保留在 Cookie 或页的 URL 中。Forms 身份验证通过 FormsAuthenticationModule 类参与到 ASP.NET 页面的生命周期中。可以通过 FormsAuthentication 类访问 Forms 身份验证信息和功能。

步骤一

Web.Config配置文件中指定验证的方式为Form,并设置跳转的登录地址和Cookie的名称,及超时时间等。

<system.web><authentication mode="Forms"> <forms loginUrl="/Home/Login" timeout="120" cookieless="UseCookies" name="LoginCookieName"></forms> </authentication> </system.web>

设置该配置文件,并不需要特意给Action传递returnUrl,就可以获取到跳转地址。

Form特性的详细说明

此时当未登录的用户访问有[Authorize]特性的Action操作时,会被跳转到Login页面,同时Login页面的URL后面会添加一个加密的ReturnUrl地址,该地址指向之前访问的有[Authorize]特性的Action地址。


步骤二

之前提到Form认证其实就是生成了一个Cookie,存放到用户的浏览器中。通过FormAuthenication.SetAuthCookie(userName,true);设置验证登录的Cookie。再通过页面跳转将Cookie响应给客户端。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel vm,string returnUrl) { if (ModelState.IsValid) { //用户名,密码验证 FormsAuthentication.SetAuthCookie(vm.UserName, true); //设置Form验证Cookie,后一个 参数为是否创建持久Cookie。及true为可以在用户浏览器上保存的。false为不在浏览器上保存。 if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } return RedirectToAction("Detail"); } else return View(vm); }

此时当我们登录以后会在浏览器中生成一个跟配置文件中名称相同的Cookie

如:

该Cookie就是我们已经登录,通过Form验证的凭证。

此时我们就可以访问那些需要登录才能访问的页面。


注销

删除对应的Cookie即可实现注销,代码如下:

[Authorize]
public ActionResult LogOut() { FormsAuthentication.SignOut();//通过Forms验证来删除Cookie return View(); } 

角色添加

有些页面可能只允许特定用户才能访问,在MVC中可以通过[Authorize(Roles="VIP")]设置Action或Controller,表示只有角色为VIP的用户才可以访问该页面。

如:只有登录且用户角色为VIP的才可以访问这个页面。

[Authorize(Roles = "VIP")]
public ActionResult VIP() { return View(); }

同时

需要在设置Form验证凭据时把用户角色添加到Cookie。

如:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel vm, string returnUrl) { if (ModelState.IsValid) { //用户名,密码验证 //FormsAuthentication.SetAuthCookie(vm.UserName, true); //设置Form验证Cookie,后一个 参数为是否创建持久Cookie。及true为可以在用户浏览器上保存的。false为不在浏览器上保存。 //if (Url.IsLocalUrl(returnUrl)) //{ // return Redirect(returnUrl); //} //return RedirectToAction("Detail"); vm.Role = "VIP"; var authTicket = new FormsAuthenticationTicket( 1, // 版本 vm.UserName, // 用户名称 DateTime.Now, // 创建日期 DateTime.Now.AddMinutes(20), // 过期时间 vm.Remember, // 是否记住 vm.Role // 用户角色 ); string encryptedTicket = FormsAuthentication.Encrypt(authTicket); var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); authCookie.HttpOnly = true;//客户端脚本不能访问 authCookie.Secure = FormsAuthentication.RequireSSL;//是否仅用https传递cookie authCookie.Domain = FormsAuthentication.CookieDomain;//与cookie关联的域 authCookie.Path = FormsAuthentication.FormsCookiePath;//cookie关联的虚拟路径 Response.Cookies.Add(authCookie); if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } return RedirectToAction("Detail"); } else return View(vm); }

在Global.asax.cs文件中重写Application_AuthenticateRequest事件

protected void Application_AuthenticateRequest(Object sender, EventArgs e) { //获取Cookie HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; if (authCookie == null || authCookie.Value == "") return; FormsAuthenticationTicket authTicket; try { //解析Cookie authTicket = FormsAuthentication.Decrypt(authCookie.Value); } catch { return; } // 解析权限 string[] roles = authTicket.UserData.Split(';'); if (Context.User != null) //把权限赋值给当前用户 Context.User = new GenericPrincipal(Context.User.Identity, roles); }

至此最简单的Form身份验证实现了。但是该Cookie只包含了用户名,没有其他信息。如果要包含其他信息,可以通过扩展用户的身份标识(HttpContext.User实例)来实现。

HttpContext.User定义如下

通过User属性可以访问Iprincipal接口的属性和方法。

//获取或设置当前 HTTP 请求的安全信息。
public IPrincipal User
{get;[SecurityPermissionAttribute(SecurityAction.Demand, ControlPrincipal = true)] set; }

所以扩展用户身份标识可以通过实现IPrincipal接口。

如:

public class MyFormsPrincipal<TUserData> : IPrincipal where TUserData : class, new() { private IIdentity _identity; private TUserData _userData; public MyFormsPrincipal(FormsAuthenticationTicket ticket, TUserData userData) { if( ticket == null ) throw new ArgumentNullException("ticket"); if( userData == null ) throw new ArgumentNullException("userData"); _identity = new FormsIdentity(ticket);//Forms身份验证 _userData = userData; } public TUserData UserData { get { return _userData; } } public IIdentity Identity { get { return _identity; } } public bool IsInRole(string role) { return false; } } 

这个方法的核心是:

  1. 在登录时,创建自定义的FormsAuthenticationTicket对象,它包含了用户信息。
  2. 加密FormsAuthenticationTicket对象。
  3. 创建登录Cookie,它将包含FormsAuthenticationTicket对象加密后的结果。
  4. 在管线的早期阶段,读取登录Cookie,如果有,则解密。
  5. 从解密后的FormsAuthenticationTicket对象中还原我们保存的用户信息。
  6. 设置HttpContext.User为我们自定义的对象。

https://www.cnblogs.com/JoeSnail/p/8250231.html


代码

如有不对,请多多指教。

转载于:https://www.cnblogs.com/sjqq/p/8821928.html

Asp.Net MVC 身份验证-Forms相关推荐

  1. asp.net mvc 身份验证中返回绝对路径的ReturnUrl

    在asp.net mvc进行身份验证只用在需要验证的Action或者Controller上标记一个[authorization]即可,如果用户没有登陆,此时将返回的ActionResult是HttpU ...

  2. ASP.NET MVC身份认证与授权

    文章目录 一.引言 1.身份认证的含义 2.身份认证与Session 基于Session保存用户状态 不足之处 二.ASP.NET身份验证 Forms验证 FormsAuthentication类 验 ...

  3. ASP.net的身份验证方式有哪些?分别是什么原理?

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

  4. ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)

    在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie ...

  5. 艾伟_转载:ASP.NET MVC数据验证

    关于ASP.NET MVC的验证,用起来很特别,因为MS的封装,使人理解起来很费解.也可能很多人都在Scott Guthrie等人写的一本<ASP.NET MVC 1.0>书中,见过Ner ...

  6. ASP.NET MVC 2 验证

    来源:http://www.cnblogs.com/jhxk/articles/2612885.html  只为把自己觉的好的存起来 对用户输入的验证以及强制业务规则/逻辑是大多数web应用的核心需求 ...

  7. ASP.NET MVC数据验证(上)

    关于ASP.NET MVC的验证,用起来很特别,因为MS的封装,使人理解起来很费解.也可能很多人都在Scott Guthrie等人写的一本<ASP.NET MVC 1.0>书中,见过Ner ...

  8. MVC身份验证及权限管理(转载)

    from https://www.cnblogs.com/asks/p/4372783.html MVC自带的ActionFilter 在Asp.Net WebForm的中要做到身份认证微软为我们提供 ...

  9. ASP.NET MVC --- 身份认证与授权

    身份认证的含义:例如在现在浏览的某宝电商网站中会经常遇到的情况,想要将某件商品加入到购物车,点击"加入购物车"之后弹出的却是登录界面.这个就是所谓的请求的身份认证 身份认证与Ses ...

最新文章

  1. php如何查询数据是否存在,PHP判断数据库中的记录是否存在的方法,php数据库_PHP教程...
  2. python @ 符号 表示矩阵乘法时的用法
  3. 带你实现开发者头条(二) 实现左滑菜单
  4. C语言之归并排序算法
  5. Transformer模型深度解读
  6. Android 仪表盘
  7. DAL调用SP时出现的异常处理
  8. iframe 去除边框 背景透明等设置 待修改
  9. WORD填空题设置下划线?
  10. uinty粒子系统子物体变大_新Unity 最新粒子系统如何用代码改变参数
  11. 设置电脑系统密码以及桌面密码
  12. 学python需要什么基础-Python入门学习需要哪些条件?
  13. java ssh超市进销存管理系统(源码+文档)【源码分享】
  14. html在js中为添加监听,使用addeventlistener为js动态创建的元素添加事件监听
  15. npm ERR! code EINTEGRITY npm! ERR! shal-
  16. Unity实现键鼠控制立方体移动旋转
  17. 山东大学计算机学院第二校园,山东大学本科生第二校园学习经历管理办法
  18. EXCEL的100种便捷用法(2):怎么将EXCEL里面一个单元格的数据拆分为多列
  19. 叉乘点乘混合运算公式_小学数学所有公式和顺口溜都在这里了,假期让孩子背熟!...
  20. Python 猴子选大王(约瑟夫环)算法

热门文章

  1. 在相册查看保存的图片
  2. 罗马书1:18-32
  3. python使用pymysql连接mysql_python3使用PyMysql连接mysql数据库的简单示例
  4. MediaCodec 编码时间戳问题
  5. 前端怎么画三角形_WEB前端-CSS三角形绘制方法
  6. [编程手记小技巧]自定义调试信息宏及gcc技巧
  7. Docker安装运行mysql
  8. qt connect函数_Qt 串口上位机开发Rice 上位机 学习开发
  9. 【httpClient】Timeout waiting for connection from pool
  10. 【FLink】cannot assign instance LinkedMap FlinkKafkaConsumerBase.pendingOffsetsToCommit