对于Web应用的表单身份验证,因为公司有一个类库,采用 Session 实现,所以一直都没有去仔细了解。其实我并不赞成在 .NET 中用 Session 实现身份验证,毕竟 .NET 提供了一个强大的身份验证体系,并且公司的类库也没有实现什么特殊的功能,仅只是保存一个 Session 变量来提供身份识别,在安全性和可用性上与 .NET 的实现相比,个人感觉还是有较大的差距。

近期很少加班,就抽空看了一下,理了个大致的思路出来。

首先,自然是配置 Web.config,在 <system.web> 下设定:

<authentication mode="Forms">

<forms name=".SomeTsteAuth"

loginUrl="admin/login.aspx"

defaultUrl="admin/index.aspx"

path="/"

timeout="10">

</forms>

</authentication>

<authentication> 的 Mode=”Forms” 指定 Web 应用采用表单验证,另外的方式还有“Windows”、“Passport”和“None”,“Windows”常用在局域网中,配合 AD 进行身份验证,“Passport”好像要交钱给微软后才能够使用,不太清楚了。“None”表示不进行验证。

<forms> 的几个常用属性:

name 属性指定验证所需要的 cookie 的名称,默认值是“.ASPXAUTH”,如果在一个服务器上下挂了多个 Web 应用程序,必须重新指定该名称,因为每个应用程序都需要唯一的 cookie。

loginUrl 属性指定登录用的页面,用于提供用户名和密码,默认值是“login.aspx”。该页面可以和需要提供身份验证才能访问的页面放在同一个目录下(呵,我原以为这个页面要放在单独的可公开访问的目录下)。

defaultUrl 属性指定登入后跳转到的页面,默认值是“default.aspx”,当然你也可以跳转到用户登入前的前一个页面,并且这是 .NET 的默认实现。

path 属性指定 cookie 的路径,默认值为“/”,对于大多数浏览器而言,cookie 的 path 是区分大小写的,因此如果路径的大小写不符,将不会发回 cookie。(注意:“/”指网站的根目录,在开发时,Visual studio 通常会在网站根目录下建立一个新的目录作为 Web 应用程序的根,例如http://localhost/MySite,此时若你要单独针对 Web 应用程序设置 path,必须从网站根目录后的路径指定,例如,要设定刚才的 Web 应用程序访问 Admin 目录下的文件需要身份验证时,path 值应为“MySite/Admin”,而不是“Admin”,否则用户将无法正常登入。)

timeout 属性指定用户多长时间不进行操作,身份凭证会过期,以分钟为单位,默认为 30 分钟。

设定好 <authentication> 以后,还需要设置 <authorication>,最常见的方式如下:

<authorization>

<deny users="?"/>

</authorization>

“?”号表示匿名用户,“*”号表示所有用户。在网上看到一些文档,在<deny users=”?” /> 下面还有一句 <allow users=”*” />,其实没必要增加这一句,除非使用角色对各个子目录分别进行权限控制。因为这样有一个潜在的危险,如果有人不小心把 <allow users=”*” /> 放在了 <deny user=”?” /> 前面,系统将不会进行验证。

如果要对子目录进行分别的权限管控,需要新增一个 <location> 段到 Web.config 的根元素 <configuration> 下:

<location path="admin">

<system.web>

<authorization>

<deny users="?"/>

</authorization>

</system.web>

</location>

如果涉及到多个子目录,并要分配不同的权限,那就需要使用角色。将 <authorization> 下的内容换成

<allow roles="Admin"/>

<deny users="*"/>

Web.config 的配置大致如此,需要注意的一点是 <authentication> 节一个 Web 应用程序只能有一个,即我们在一个 Web 应用程序中只能采用一种验证方式,而 <location> 节可以配置多个,以对各目录进行不同的权限管控。对于未配置 <authorization> 节的目录,访问权限与 Web 应用程序根相同,若应用程序的根也未配置 <authorization>,则默认为任何人可访问,即使 <authentication> 的 mode 属性设置为“Forms”。

其次就是编码,在登录页面的“登录”按钮点击事件中:

if (UserName.Text.Trim() == "你的用户名" && Password.Text == "你的密码")

FormsAuthentication.RedirectFromLoginPage("你的用户名", false);

else

//提示用户名和密码不正确

RedirectFromLoginPage() 的第一个参数是目前正在验证的用户名,第二个参数指是否长期保存登录信息到 cookie 中,这个参数的意义在 .NET 2.0 中与 .NET 1.1 中不同,在 .NET 1.1 中,会将登录信息保存到 cookie 中,并设定过期时间为 50 年后,即你以后再也不用输入用户名和密码,除非 cookie 被删除或 50 年后(老眼昏花的你加上一台堪称古董的电脑,最美不过夕阳红)。在 .NET 2.0 中,这个参数仅指在关闭浏览器后,登录信息在 cookie 中是否还存在,而过期时间的约束依然有效,即 cookie 过期后,无论你重启浏览器与否,仍需输入登录凭证。

代码简单得出乎意料,.NET 会自动创建票劵并重定向到登录前用户访问的那个需要进行验证的页面,若用户直接访问登录页面,则重定向到 Web.config 中定义的 default 页面。如果需要自己控制重定向的过程,可以这么做:

if (UserName.Text.Trim() == "你的用户名" && Password.Text == "你的密码")

{

FormsAuthentication.SetAuthCookie("你的用户名", false);

Response.Redirect("Index.aspx");

}

else

//提示用户名和密码不正确

其实,语句 FormsAuthentication.RedirectFromLoginPage("你的用户名", false) 等同于

FormsAuthentication.SetAuthCookie("你的用户名", false);

Response.Redirect(FormsAuthentication.GetRedirectUrl("你的用户名", false));

当然,也可以手动创建票劵,并加入到响应的 cookie 集合中,完整的代码如下:

if (UserName.Text.Trim() == "你的用户名" && Password.Text == "你的密码")

{

//为当前登录用户创建一个新的票劵

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(

2, //版本号

"你的用户名", //登录的用户名

DateTime.Now, //票劵发布时间

DateTime.Now.AddMinutes(15), //票劵过期时间

false, //是否在关闭浏览器后仍然保留登录信息

"", //可加入少量用户数据(注意:不能为 null)

FormsAuthentication.FormsCookiePath //cookie 路径

);

//加密票劵,获取加密后的字串

string encrypt = FormsAuthentication.Encrypt(ticket);

//使用加密后的字串建立一个 cookie

HttpCookie cookie = new HttpCookie(

FormsAuthentication.FormsCookieName,

Encrypt

);

//将 cookie 增加到客户端

Response.Cookies.Add(cookie);

Response.Redirect(FormsAuthentication.GetRedirectUrl("你的用户名", false));

}

else

//提示用户名和密码不正确

到这里,应该很清楚了,表单验证,其实质是使用一个特定的 cookie,在每次连接服务器时验证该 cookie 是否存在,从而决定用户是否具有相应的权限。在上述代码中,也可以增加对 cookie 控制的代码,在使用加密后的票劵建立一个 cookie 后,增加代码:

//HttpOnly 属性为 true,表示该 cookie 不能在浏览器端进行存取

cookie.HttpOnly = true;

//cookie 的路径,取 Web.config 中 <forms> 属性 path 的值

cookie.Path = FormsAuthentication.FormsCookiePath;

//设置 cookie 的过期时间,与票劵的过期时间一致,如果这两个时间不一致,则其中任何一个时间到期时,均视为过期

cookie.Expires = ticket.Expiration;

清楚表单验证的大致机制后,对于基于角色的表单验证也是手到擒来,大致的过程叙述如下:

1 在登录页面的代码文件中,新增一个普通的 cookie,将用户所属的角色保存到该 cookie 中(一个用户可具备多个角色)。

2 在 Global.asax 的 AuthenticateRequest 事件中,判断用户是否已通过验证,若已通过验证,则从1增加的 cookie 中取出角色字符串,并构建一个 System.Security.Principal.GenericPrincipal 对象,该对象的构造函数包括两个参数:用户标识和角色数组,用户标识可通过 HttpContext.Current.User.Identity 取得,角色数组将角色字符串转换为字符串数组赋进去即可。

3 调整 Web.config 设置角色的权限。

转载于:https://www.cnblogs.com/ITEagle/archive/2011/11/22/2258914.html

【转】ASP.NET 表单验证实现浅析相关推荐

  1. asp.net 2.0 下的表单验证Cookieless属性

    刚刚在洗衣服的时候突然想到今天在做WAP程序的表单验证的时候遇到一个问题,在不支持Cookies的移动设备模拟器中无法正常进行表单验证,联想到昨天使用web.config设置cookieless属性时 ...

  2. Asp.net2.0下的表单验证Cookieless属性

    刚刚在洗衣服的时候突然想到今天在做WAP程序的表单验证的时候遇到一个问题,在不支持Cookies的移动设备模拟器中无法正常进行表单验证,联想到昨天使用web.config设置cookieless属性时 ...

  3. Asp.net Authenticatiion Authorization(认证与授权)——表单验证

    本文大量摘抄 asp.net Forms表单验证 使用经验及验证流程分析 尽管使用Asp.net做过几个简单项目,但是一直没有真正理解认证和授权这一块是怎么回事.打开vs 2015/2017的模板,却 ...

  4. 基于 猫冬的 jQuery formValidator表单验证 的asp.net 控件

    为了方便在asp.net中使用,封装了一下 <猫冬 的 jQuery formValidator表单验证> 控件 其实也不是什么控件,只是一个类,方便生成前台js. 特点: 1.后台生成的 ...

  5. JQuery表单验证插件EasyValidator,超级简单易用!

    本插件的宗旨是:用户无需写一行JS验证代码,只需在要验证的表单中加入相应的验证属性即可,让验证功能易维护,可扩展,更容易上手. DEMO中已经包含了常用的正则表达式,可以直接复用,为了考虑扩展性,所以 ...

  6. WCF服务实现客户端Cookie共享,表单验证的解决方案

    基于前几篇的文章,如果理解了通道 拦截器  服务转发的概念,相信你肯定也能理解咋的玩了. 说白了就是创建客户端的拦截器: 实现接口:IClientMessageInspector. 里面的方法就是客户 ...

  7. MOSS2007中实现表单验证

    MOSS2007中实现表单验证 转自阿喜的Spaces Microsoft Office SharePoint Server 2007 Forms Authentication 本文将演示如何在MOS ...

  8. JavaScript 表单验证

    JavaScript 可用来在数据被送往服务器前对 HTML 表单中的这些输入数据进行验证. 被 JavaScript 验证的这些典型的表单数据有: 用户是否已填写表单中的必填项目? 用户输入的邮件地 ...

  9. 表单验证的初步实现和省市级联

    1.表单验证的初步实现 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/T ...

最新文章

  1. vivo系统如何没root激活Xposed框架的经验
  2. 完美解决Ubuntu16.04虚拟机窗口自适应问题
  3. windows系统和linux系统可以使用相同的js代码吗_使用Sboxr自动发现和利用DOM(客户端)XSS漏洞...
  4. 集算器并行处理大文本文件的示例
  5. 邮政计算机网络,邮政计算机网络论文(共2018字).doc
  6. 局部内部类如何访问外部类方法中变量
  7. vsftpd增加用户 linux,Ubuntu Linux中vsFTP添加用户
  8. makefile 生成.o_要学好 C 语言 / C++ ,Makefile 可少不了
  9. [轉]PHP执行MYSQL存储过程报错:Commands out of sync; you can't run this command now 问题的解决...
  10. 利用python自动发送邮件(无敌详细讲解版)
  11. Android键盘删除键问题
  12. 数学分析(1):集合相关公式的证明
  13. spark-submit 命令使用详解
  14. 李沐动手学深度学习V2-attention注意力机制
  15. 什么是好代码-代码整洁之道阅读笔记
  16. VB创建写字板小程序
  17. 已知正方形面积求边长c语言,正方形知道面积怎么求边长.
  18. matlab在振动信号处理中的应用pdf,matlab在振动信号处理中的应
  19. 基于Java的微信公众号二次开发视频教程
  20. yum安装的时候报错Couldn't open file /mnt/repodata/repomd.xml

热门文章

  1. Python中非纯文本文件的读取
  2. android 在指定位置添加布局,Android 如何动态添加 View 并显示在指定位置。
  3. oracle日期的sql,Oracle中一些和日期有关的SQL查询
  4. 带哨兵节点的链_Redis 哨兵节点之间相互自动发现机制(自动重写哨兵节点的配置文件)...
  5. 米勒机会信托或将通过GBTC投资比特币
  6. SAP License:SAP FI/CO 基本概念
  7. java获取项目路径
  8. Spring课程 Spring入门篇 总结
  9. JZOJ 5914. 盟主的忧虑
  10. CentOS 7.3 关闭默认防火墙远程登录