2004-11-3 + 扩展Forms验证
1.使用Forms验证存储用户自定义信息
Forms验证在内部的机制为把用户数据加密后保存在一个基于cookie的票据FormsAuthenticationTicket中,因为是经过特殊加密的,所以应该来说是比较安全的。而.net除了用这个票据存放自己的信息外,还留了一个地给用户自由支配,这就是现在要说的UserData。
UserData可以用来存储string类型的信息,并且也享受Forms验证提供的加密保护,当我们需要这些信息时,也可以通过简单的get方法得到,兼顾了安全性和易用性,用来保存一些必须的敏感信息还是很有用的。
下面来看怎么使用UserData,然后会给出一个实际使用的例子。
//创建一个新的票据,将客户ip记入ticket的userdata
FormsAuthenticationTicket ticket=new FormsAuthenticationTicket(
1,userName.Text,DateTime.Now,DateTime.Now.AddMinutes(30),
false,Request.UserHostAddress);
//将票据加密
string authTicket=FormsAuthentication.Encrypt(ticket);
//将加密后的票据保存为cookie
HttpCookie coo=new HttpCookie(FormsAuthentication.FormsCookieName,authTicket);
//使用加入了userdata的新cookie
Response.Cookies.Add(coo);
下面是FormsAuthenticationTicket构造函数的重载之一的方法签名
public FormsAuthenticationTicket(
int version,
string name,
DateTime issueDate,
DateTime expiration,
bool isPersistent,
string userData
);
参数
version
版本号。
name
与身份验证票关联的用户名。
issueDate
Cookie 的发出时间。
expiration
Cookie 的到期日期。
isPersistent
如果 Cookie 是持久的,为 true;否则为 false。
userData
将存储在 Cookie 中的用户定义数据
使用userdata也很简单,FormsIdentity的Ticket属性就提供了对当前票据的访问,获得票据后就可以用UserData属性访问保存的信息,当然是经过解密的。
((System.Web.Security.FormsIdentity)this.Context.User.Identity).Ticket.UserData
下面是一个具体的应用。
由于Forms验证是通过cookie来进行的,它需要传递一个票据来进行工作。虽然票据是加密的,里面的内容不可见,但这并不能阻止别人用一个假冒的身份使用票据(就像我们可以拿别人的钥匙去开别人的锁),比较常见的就是不同ip的用户在不安全通道截获了这个票据,然后使用它进行一些安全范围外的活动。
解决这个问题的办法之一就是使用SSL来传递信息。
但是如果不能使用SSL呢?我们可以判断ip和票据是否匹配,如果发出请求的ip是初次产生票据的ip,则没有问题,否则就销毁这个票据。
为此,我们需要在一开始处理登录时将用户的ip保存起来,这样就可以在以后的请求中随时验证后继请求的ip是否和初始ip相同。保存这个敏感ip的最佳场所当然是UserData啦,而验证的时机则是在AuthenticateRequest事件发生时,即Global.aspx.cs中定义的处理此事件的Application_AuthenticateRequest方法中。
上面的示例实际上已经是把用户ip保存到了UserData中,下面是验证的过程。
if(this.Request.IsAuthenticated)
{
if(((System.Web.Security.FormsIdentity)this.Context.User.Identity).Ticket.UserData !=this.Request.UserHostAddress)
{
System.Security.Principal.GenericIdentity gi=new System.Security.Principal.GenericIdentity("","");
string[] rolesi={};
System.Security.Principal.GenericPrincipal gpi=new System.Security.Principal.GenericPrincipal(gi,rolesi);
this.Context.User=gpi;
}
}
通过给GenericPrincipal空的GenericIdentity和roles使票据失效,这样将强迫用户重新登录。为了测试这个方法,可以先把条件改为相等,看效果如何 :)
这个方法也有不足之处,具体为
1.使用同一代理的用户将拥有同一个ip,这样就不能防范此类假冒攻击了
2.如果用户使用动态ip,则可能造成正常用户被我们强行销毁票据。
不过总的来说,这个办法还是比较可行的。
2.使用安全特性配合Forms验证进行安全操作。
PrincipalPermissionAttribute可以配合Forms验证进行基于角色或用户的安全验证,该特性不能用于程序集级别。它的作用范围可以是类或具体的方法。来看一个简单的示例。
[PrincipalPermission(SecurityAction.Demand,User="Notus")]
public class Test : BasePage
{
private void Page_Load(object sender, System.EventArgs e)
{
try
{
this.sayHello();
this.sayHello2();
}
catch(Exception ex)
{
Response.Write(ex.ToString());
}
}
private void sayHello()
{
Response.Write("hello world!");
}
private void sayHello2()
{
Response.Write("hello PrincipalPermissionAttribute!");
}
#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
注意这个例子一开始是作用于整个类的,生成后执行,如果当前用户不是Notus,就会发生异常System.Security.SecurityException,提示对主体权限的请求失败。反之,则可以顺利访问,并输出两个hello world!,注意是两个。现在的安全作用范围是整个类。
接下来我们改一下特性的作用范围。将特性声明移到sayHello2方法上面,重新编译后运行,就会发现程序在运行到sayHello2方法后抛出了System.Security.SecurityException。这说明现在安全作用范围缩小到了方法级别。
该特性可以通过设置User和Role来进行基于用户和角色的安全保护。另外其使用的第一个参数是SecurityAction枚举,该枚举设置了具体的保护级别或措施。像我们现在使用的这个Demand,是要求调用堆栈中的所有高级调用方都已被授予了当前权限对象所指定的权限。
下面是msdn给的示例
示例
下面的示例说明可以如何以声明方式使用 PrincipalPermission 要求当前用户是 Bob 并且属于 Supervisor 角色。
[PrincipalPermissionAttribute(SecurityAction.Demand, Name="Bob",
Role="Supervisor")]下面的示例说明如何要求当前用户的身份是 Bob,与角色成员条件无关。
[PrincipalPermissionAttribute(SecurityAction.Demand, Name="Bob")]
下面的示例说明如何仅要求对用户进行身份验证。
[PrincipalPermissionAttribute(SecurityAction.Demand, Authenticated=true)]
再要说一下的是,这里面的User和Role是可以和Forms验证集成的,据此,我们可以在一些重要的类或方法中使用PrincipalPermissionAttribute,以将自己的程序武装到家。
而实际上,该特性的作用远不止这些,更详细的信息可以查阅msdn。
2004-11-3 + 扩展Forms验证相关推荐
- SharePoint2007 配置MOSS基于AD的Forms验证
公司上边要求使用Forms验证方式登陆到MOSS系统 于是经过研究测试成功了, 这次上边又要求用户必须为AD用户 查了很多资料 经过了一番周折 终于测试成功了,无奈网上文章转载的太多, 差错太多,特将 ...
- Easyui validatebox修改——1.当text发生变化时在校验,2.取消校验,3扩展自定义验证
1.当text发生变化时在校验: Easyui validatebox个人感觉还是比较好用的,但是发现他不是只有text改变并离开编辑框的时候才验证,而是不停的做验证:如果是js脚本的本地验证还好,如 ...
- 再次探扩展-对xVal进行扩展解决验证不同步的问题
之前写过两篇文章,分别都是在ASP.NET MVC下进行验证的,分别如下: <ASP.NET MVC中的验证> <ASP.NET MVC验证框架中关于属性标记的通用扩展方法> ...
- Asp.net中基于Forms验证的角色验证授权[转]
Asp.net的身份验证有有三种,分别是"Windows | Forms | Passport",其中又以Forms验证用的最多,也最灵活. Forms 验证方式对基于用户的验证授 ...
- Nancy之Forms验证
授权几乎是所以系统都不可或缺的部分,在Nancy中怎么授权呢?我们这篇博文来说一下Nancy的Forms授权. 首先在NuGet上安装Nancy.Authentication.Forms Nancy的 ...
- 浅谈ASP.NET Forms验证
ASP.NET Forms验证 用户验证是每一个项目必须的一个模块,由于已经很久没有碰到这一块内容,今天写一个用户验证居然脑子一片空白.于是乎就和一个同事进行了一片讨论,晚上回家决定把讨论的结果给记录 ...
- 在Forms验证模式下,实现多个站点(SubDomain相同)共享同一用户登录状态
原文:http://caomao.cnblogs.com/archive/2005/07/05/186606.html 今天一早看了dudu关于二级域名Cookie的问题及解决方法,认为dudu的原理 ...
- MVC Controllers和Forms验证
想想下,一组从Forms验证抽象出来的登入/登出Controllers行为特有的ActionResult实现.. 我已经使用ASP.NETMVC重新实现了我的个人网站(projects.nikhilk ...
- 【转载】Asp.Net中基于Forms验证的角色验证授权
Asp.Net的身份验证有有三种,分别是"Windows | Forms | Passport",其中又以Forms验证用的最多,也最灵活. Forms 验证方式对基于用户的验证授 ...
最新文章
- 【EMC】电磁兼容性相关名词解释、基础知识
- poj1182 and 携程预赛2第一题 带权并查集
- GridView列表数据的添加
- 形态数轴的非递进现象
- 系列笔记 | 深度学习连载(2):梯度下降
- Android开发技巧——自定义控件之自定义属性
- python 的内存回收,及深浅Copy详解
- RabbitMQ消息确认机制
- java erlang 游戏_游戏中最近可达点(用erlang写一个简单算法)
- Python之Pandas库
- 计算机硬件如何分类,计算机硬件分类教学.doc
- linux挂载时间3秒,linux基础学习(十一) 时间的同步 设备的挂载
- rabbitmq接收不到消息_分布式消息队列:如何保证消息的可靠性传输
- t分布f分布与样本均值抽样分布_T检验和其他假设检验的P值怎么理解
- gif透明背景动画_用“万彩动画大师”点亮你的微课
- 计算机安全模式无法启动修复,win7旗舰版安全模式故障修复教程
- 计算机教师格言座右铭,教师教育格言座右铭
- ERROR 1370 (42000): execute command denied to user ‘james‘@‘localhost‘ for routine ‘test.coun_add‘
- 抖音是怎么动摇美国国本的?
- 第三方支付系统-支付流程