ASP.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 设置角色的权限。
(本文转自:http://blog.csdn.net/orain/article/details/3279660)
ASP.NET 表单验证实现浅析的更多相关文章
- ASP.NET 表单验证方法与客户端(浏览器)服务器交互机制的故事
想到这个问题完全是一个意外吧,是在寻找另外一个问题答案的过程中,才对验证方法与浏览器服务器交互机制的关系有了清晰的认识. 先说下验证方法,验证方法分为前台验证和后台验证. 前台验证就是类似jQuery ...
- ASP.NET 表单验证
静态脚本 oncilentClick() 静态使用方法 也可以$获取ID动态添加脚本 1.Response.Write(); 2.通过Register方式 3.Attribus方式根据控件ID进行添加 ...
- php基本(四)表单验证
本文内容来自http://www.w3school.com.cn/php/php_form_url_email.asp PHP 表单验证 - 验证 E-mail 和 URL 本节展示如何验证名字.电邮 ...
- SharePoint2010基于表单验证方法总结(转载)
系统环境: win2008r2+ sql2008r2 +Visual Studio2010+sharepoint 2010 A.如果已经建立了web application 例如名字为: http: ...
- ASP.NET MVC Jquery Validate 表单验证的多种方式
在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体验也会得到很大的提升.在开发过程中我们可以不借助 JS 库,自己去手写 JS ...
- asp.net 登陆验证 Form表单验证的3种方式 FormsAuthentication.SetAuthCookie;FormsAuthentication.RedirectFromLoginPage;FormsAuthenticationTicket
我们在登陆成功后,使用下面的3种方法,都是同一个目的:创建身份验证票并将其附加到 Cookie, 当我们用Forms认证方式的时候,可以使用HttpContext.Current.User.Ident ...
- [转]ASP.NET MVC Jquery Validate 表单验证的多种方式介绍
在我们日常开发过程中,前端的表单验证很重要,如果这块处理不当,会出现很多bug .但是如果处理的好,不仅bug会很少,用户体验也会得到很大的提升.在开发过程中我们可以不借助 JS 库,自己去手写 JS ...
- ASP.NET MVC Form表单验证与Authorize特性
一.Form表单验证 1.基本概念 表单验证是一个基于票据(ticket-based)[也称为基于令牌(token-based)]的系统.当用户登录系统以后,会得到一个包含基于用户信息的票据(tick ...
- Asp.net Mvc 表单验证(气泡提示)
将ASP.NET MVC或ASP.NET Core MVC的表单验证改成气泡提示: //新建一个js文件(如:jquery.validate.Bubble.js),在所有要验证的页面引用 (funct ...
随机推荐
- Selenium2入门(一)简介
Selenium 是一款有名的 Web 应用程序测试框架,用于进行功能测试.新版本 Selenium 2 结合了 Selenium 1 和 WebDriver(Selenium 的并行项目)中的最佳特 ...
- oracle基础教程(8)oracle修改字符集
oracle基础教程(8)oracle修改字符集 1.用dba连接数据库 -->sqlplus / as sysdba 2.查看字符集 -->SELECT parameter, value ...
- Nginx上传文件失败
公司用Nginx做反向代理,出现了上传文件失败的问题,通过查看错误日志,发现是上传文件太大的缘故. 通过查找资料,才知道nginx默认最大上传文件时1M.这就需要修改配置文件,将上传文件大小进行修改. ...
- MySQL服务 - MySQL变量类型及变量设置
一.MySQL变量类型: MySQL通过变量来定义当前服务器的特性,保存状态信息等.我们可以通过手动更改变量的值来配置MySQL,也可以通过变量获得MySQL的当前状态信息.MySQL的变量类型可以从 ...
- Node.js的循环与异步问题
(转自:http://bbs.tianya.cn/post-itinfo-280080-1.shtml) Node.js 的异步机制由事件和回调函数实现,一开始接触可能会感觉违反常规,但习惯 以后就会 ...
- mybatis动态调用表名和字段名
以后慢慢启用个人博客:http://www.yuanrengu.com/index.php/mybatis1021.html 一直在使用Mybatis这个ORM框架,都是使用mybatis里的一些常用 ...
- Click模块化路由器
[概述] Click是一种基于软件控制的模块化路由器.其架构可以大致视为一系列数据包处理模块(称为elements)组成的.一个Click路由器可以看成一张由elements作为顶点,数据包传递路径作 ...
- 如何将win7变为wifi热点
以前经常使用connectify软件一键设置win7热点,但发现该软件影响开机速度,于是研究了一下win7自带的wifi功能,简单方便,分享如下: 1.打开命令提示符: [开始]/搜索框中输入“cmd ...
- unity 读取文本与写入文本
void writeData(string str,string file) { string parth = Application.dataPath; Strea ...
- IOS 中openGL使用教程3(openGL ES 入门篇 | 纹理贴图(texture)使用)
在这篇文章中,我们将学习如何在openGL中使用纹理贴图. penGL中纹理可以分为1D,2D和3D纹理,我们在绑定纹理对象的时候需要指定纹理的种类.由于本文将以一张图片为例,因此我们为我们的纹理对象 ...