Asp.Net实现FORM认证的一些使用技巧(转)
2016-07-16 20:20
561 查看
最近因为项目代码重构需要重新整理用户登录和权限控制的部分,现有的代码大体是参照了.NET的FORM认证,并结合了PORTAL KITS的登录控制,代码比较啰嗦,可维护性比较差。于是有了以下的几个需求(大多数系统应该都会碰到):
用.NET自带的FORM认证来实现安全登录
登录后需要记录登录用户的基本信息,方便所有页面调用
记录本机登录状态,短时间关闭窗口后不用重新登录
权限控制和代码的文件夹结构相呼应,即按角色允许访问不同的目录
权限控制有可能需要细化到每一个页面,即按角色允许访问不同的页面
以上的部分尽量自己少写代码,用自带的类库和机制实现
第一步:准备工作
先准备一个名为Test的WEB项目,包含:
Default.aspx,默认页,随便显示一些信息,
Login.aspx,登录页,上面放两个文本框,用来输入用户名和密码,一个登录按钮,一个指向Register.aspx的超链,
Register.aspx,用户注册页,注册用户信息,随便放一点文本框,主要是模拟一下注册,不用真正实现,
Web.config,配置页面。
注册页与登录页在同一目录的机妙后面会说。
第二步:Web.config文件的修改
1、打开Web.config文件,找到authentication节,将其改为如下:
代码
上面的代码,实际上类似于手工实现了SetAuthCookie方法的过程。
首先,模拟实现登录,我们手动设置了一个UserInfo的对象,string strUser = Serialize.Encrypt<UserInfo>(user) 是将对象序列化成字符串的一个方法。
然后,生成一个FormsAuthenticationTicket票据。此处用到的FormsAuthenticationTicket构造函数的重载方法的签名解释
代码
其中,name的设置与Context.User.Identity.Name对应,且大小写敏感,也与将来的权限控制相关,赋值的时候需要特别注意。另外,票据的到期日期和Web.config中设置的Cookie的到期日期不是同一个概念,如果分不清,请到网上去搜索,如果实在不想在这上下功夫,后面会有处理的方法。
再后,string strTicket = FormsAuthentication.Encrypt(ticket) 将票据加密成字符创
最后,HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strTicket) 生成Cookie。
FormsAuthentication.FormsCookieName获取的就是Web.config中配置的Cookie名称,也就是默认验证时产生的Cookie。cookie.Expires = ticket.Expiration 将票据的过期时间和Cookie的过期时间做了同步,也就避免了两者不同所产生的矛盾。这样,验证票据生成了,存储到默认配置的Cookie中,也就是类似实现了一个SetAuthCookie方法的过程。通过Context.User就能获取票据的相关信息了。
3、获取信息
为了在其他登录后的页面比较简单的获取登录用户信息,我们先生成一个基类页面。在AppCode中新增LoginBasePage类,代码如下:
代码
再将文件夹ManageAdmin下的Web.config文件的<allow users="Admin"></allow>改成<allow roles="Administrators"></allow>。
最后,修改代码。
1、注意,我们在模拟用户信息的时候,有这么一句,user.Roles = "Administrators,Users";也就是用户Admin具备两种角色
2、为模拟Users组的用户登录,我们再添加如下代码:
代码
这样,我们登录时,输入“Admin”和“User1”的时候,就可以模拟不同角色的用户登录了。
3、Forms基于角色的验证的内部机制是,将角色的属性也设置到了Context.User中,这里也需要手工代码处理一下。
首先,为了支持基于角色的验证,我们每进入一个页面都需要将角色信息设置到Context.User中,那么最好的办法就是在Global.asax 文件中的Application_AuthenticateRequest方法中设置。
Application_AuthenticateRequest方法,是在每次验证请求时触发,它与另外一个方法
Application_BeginRequest的区别就在于,Application_AuthenticateRequest方法内,能够访问
Context.User.Identity,而Application_BeginRequest则无法访问。
我们在根目录添加一个Global.asax 文件,增加如下代码:
代码
此处,主要代码就是将Context.User.Identity强制转换为FormsIdentity类的对象,通过访问Ticket属性的UserData属性,获得被序列化后的对象的字符串,最后用方法Serialize.Decrypt<UserInfo>(strUser)将字符串反序列化成对象,再将UserInfo对象的Roles属性以“,”为分隔符分隔成角色数组,再用Context.User.Identity和角色数组生成一个新的GenericPrincipal对象,赋值给Context.User ,则Context.User 为已经设置好角色的验证对象。
按照我们的设置,Admin用户能访问两个目录,而User1用户,则只能访问ManageUsers一个目录。
第五步:集中管理Web.config文件
目录的访问权限控制,是按用户还是按角色,一般由具体业务决定。
但是,随着目录的增多,每个目录下都存在一个Web.config文件,管理起来特别不方便。
通过上面提到过的location节的path属性,我们可以实现Web.config配置的统一管理。我们可以将各个文件或目录的配置都放置在根目录的Web.config文件内,代码如下:
<configuration>
<appSettings/>
<connectionStrings/>
<location path ="Register.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<location path ="ManageAdmin">
<system.web>
<authorization>
<allow roles="Administrators"></allow>
<deny users="*"></deny>
</authorization>
</system.web>
</location>
<location path ="ManageUsers">
<system.web>
<authorization>
<allow roles="Users"></allow>
<deny users="*"></deny>
</authorization>
</system.web>
</location>
<system.web>
<!-- 这里放置原来根目录 Web.config 的内容,就不列出来了 -->
</system.web>
</configuration>
结尾:
这次彻底理顺FORM验证的过程,发现了不少实用性很强的技巧,中间参考了很多网友的文章,也通过Reflector看了一下具体实现的源代码。感觉收获不少,最大的收获就是对于问题不但要知其然更要知其所以然,要有一种打破沙锅问到底的净胜。
大家如果有什么问题有什么疑问,不但要找到解决的办法,有时间的话最好从理论到底层代码都好好过一过,对自己的水平长进有很大的帮助。
这篇文章还有很多方面没有涉及,也有很多高深的东西没有讲到,例如“通过PrincipalPermissionAttribute配合Forms验证进行基于角色或用户的安全验证”。就当留给自己一个研究的尾巴吧。
用.NET自带的FORM认证来实现安全登录
登录后需要记录登录用户的基本信息,方便所有页面调用
记录本机登录状态,短时间关闭窗口后不用重新登录
权限控制和代码的文件夹结构相呼应,即按角色允许访问不同的目录
权限控制有可能需要细化到每一个页面,即按角色允许访问不同的页面
以上的部分尽量自己少写代码,用自带的类库和机制实现
第一步:准备工作
先准备一个名为Test的WEB项目,包含:
Default.aspx,默认页,随便显示一些信息,
Login.aspx,登录页,上面放两个文本框,用来输入用户名和密码,一个登录按钮,一个指向Register.aspx的超链,
Register.aspx,用户注册页,注册用户信息,随便放一点文本框,主要是模拟一下注册,不用真正实现,
Web.config,配置页面。
注册页与登录页在同一目录的机妙后面会说。
第二步:Web.config文件的修改
1、打开Web.config文件,找到authentication节,将其改为如下:
代码
上面的代码,实际上类似于手工实现了SetAuthCookie方法的过程。
首先,模拟实现登录,我们手动设置了一个UserInfo的对象,string strUser = Serialize.Encrypt<UserInfo>(user) 是将对象序列化成字符串的一个方法。
然后,生成一个FormsAuthenticationTicket票据。此处用到的FormsAuthenticationTicket构造函数的重载方法的签名解释
代码
其中,name的设置与Context.User.Identity.Name对应,且大小写敏感,也与将来的权限控制相关,赋值的时候需要特别注意。另外,票据的到期日期和Web.config中设置的Cookie的到期日期不是同一个概念,如果分不清,请到网上去搜索,如果实在不想在这上下功夫,后面会有处理的方法。
再后,string strTicket = FormsAuthentication.Encrypt(ticket) 将票据加密成字符创
最后,HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strTicket) 生成Cookie。
FormsAuthentication.FormsCookieName获取的就是Web.config中配置的Cookie名称,也就是默认验证时产生的Cookie。cookie.Expires = ticket.Expiration 将票据的过期时间和Cookie的过期时间做了同步,也就避免了两者不同所产生的矛盾。这样,验证票据生成了,存储到默认配置的Cookie中,也就是类似实现了一个SetAuthCookie方法的过程。通过Context.User就能获取票据的相关信息了。
3、获取信息
为了在其他登录后的页面比较简单的获取登录用户信息,我们先生成一个基类页面。在AppCode中新增LoginBasePage类,代码如下:
代码
再将文件夹ManageAdmin下的Web.config文件的<allow users="Admin"></allow>改成<allow roles="Administrators"></allow>。
最后,修改代码。
1、注意,我们在模拟用户信息的时候,有这么一句,user.Roles = "Administrators,Users";也就是用户Admin具备两种角色
2、为模拟Users组的用户登录,我们再添加如下代码:
代码
这样,我们登录时,输入“Admin”和“User1”的时候,就可以模拟不同角色的用户登录了。
3、Forms基于角色的验证的内部机制是,将角色的属性也设置到了Context.User中,这里也需要手工代码处理一下。
首先,为了支持基于角色的验证,我们每进入一个页面都需要将角色信息设置到Context.User中,那么最好的办法就是在Global.asax 文件中的Application_AuthenticateRequest方法中设置。
Application_AuthenticateRequest方法,是在每次验证请求时触发,它与另外一个方法
Application_BeginRequest的区别就在于,Application_AuthenticateRequest方法内,能够访问
Context.User.Identity,而Application_BeginRequest则无法访问。
我们在根目录添加一个Global.asax 文件,增加如下代码:
代码
此处,主要代码就是将Context.User.Identity强制转换为FormsIdentity类的对象,通过访问Ticket属性的UserData属性,获得被序列化后的对象的字符串,最后用方法Serialize.Decrypt<UserInfo>(strUser)将字符串反序列化成对象,再将UserInfo对象的Roles属性以“,”为分隔符分隔成角色数组,再用Context.User.Identity和角色数组生成一个新的GenericPrincipal对象,赋值给Context.User ,则Context.User 为已经设置好角色的验证对象。
按照我们的设置,Admin用户能访问两个目录,而User1用户,则只能访问ManageUsers一个目录。
第五步:集中管理Web.config文件
目录的访问权限控制,是按用户还是按角色,一般由具体业务决定。
但是,随着目录的增多,每个目录下都存在一个Web.config文件,管理起来特别不方便。
通过上面提到过的location节的path属性,我们可以实现Web.config配置的统一管理。我们可以将各个文件或目录的配置都放置在根目录的Web.config文件内,代码如下:
<configuration>
<appSettings/>
<connectionStrings/>
<location path ="Register.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<location path ="ManageAdmin">
<system.web>
<authorization>
<allow roles="Administrators"></allow>
<deny users="*"></deny>
</authorization>
</system.web>
</location>
<location path ="ManageUsers">
<system.web>
<authorization>
<allow roles="Users"></allow>
<deny users="*"></deny>
</authorization>
</system.web>
</location>
<system.web>
<!-- 这里放置原来根目录 Web.config 的内容,就不列出来了 -->
</system.web>
</configuration>
结尾:
这次彻底理顺FORM验证的过程,发现了不少实用性很强的技巧,中间参考了很多网友的文章,也通过Reflector看了一下具体实现的源代码。感觉收获不少,最大的收获就是对于问题不但要知其然更要知其所以然,要有一种打破沙锅问到底的净胜。
大家如果有什么问题有什么疑问,不但要找到解决的办法,有时间的话最好从理论到底层代码都好好过一过,对自己的水平长进有很大的帮助。
这篇文章还有很多方面没有涉及,也有很多高深的东西没有讲到,例如“通过PrincipalPermissionAttribute配合Forms验证进行基于角色或用户的安全验证”。就当留给自己一个研究的尾巴吧。
相关文章推荐
- 使用ASP.Net WebAPI构建REST服务(二)——路由
- 使用ASP.Net WebAPI构建REST服务(一)——简单的示例
- Use the Raspberry Pi as a DIY Surveillance camera
- Asp.net总结
- (翻译)从底层了解ASP.NET体系结构
- Asp.Net连接Mysql报错Out of sync with server
- asp.net EF 反向工程 CodeFirst 参数错误异常
- 香蕉派 banana pi BPI-M2+ 四核开发板 全志 allwinner H3方案
- asp.net使用mysql数据库
- 菜鸟级三层框架(EF+MVC)项目实战之 系列四 UI层ASP.NET MVC实现CRUD
- .aspx文件和.aspx.cs文件的区别与联系
- .aspx文件和.aspx.cs文件的区别与联系
- ASP.NET MVC进阶之路:深入理解依赖注入(DI)和控制反转(IOC)
- 【Dongle】【牛腩新闻发布系统】ASP无法识别
- ASP汉字转拼音函数的方法
- ASP.NET MVC4 导出Excel问题
- 使用jaspersoft创建jasper模板的经验总结
- ASP.NET MVC路由系统的核心对象介绍
- ASP.Net Core-依赖注入IoC
- asp.net获取文件夹下的所有文件