艾伟:ASP.NET安全问题--Forms验证的具体介绍(上篇)

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介:   本篇的话题如下:  Forms验证的工作原理  Forms验证中的API  Forms验证的工作原理  我们知道,Forms验证主要是基于cookie的,说白一点就是:把用户信息保存在cookie中,然后发送到客户端;再就是解析客户端的发送了的cookie信息,进行解析,然后进行验证。

  本篇的话题如下:

  Forms验证的工作原理

  Forms验证中的API

  Forms验证的工作原理

  我们知道,Forms验证主要是基于cookie的,说白一点就是:把用户信息保存在cookie中,然后发送到客户端;再就是解析客户端的发送了的cookie信息,进行解析,然后进行验证。关于cookieless的工作原理和方法,我这里不赘述,大家可以参看我的另外的一片文章:浅谈ASP.NET内部机制(一)。

  当匿名用户请求一个需要验证后才能访问的资源和页面的时候,那么如果采用了Forms验证,那么URL授权模块就会把用户重定向到登录页面。而之前请求的URL就会被保存起来,等到用户正确的登录后,就再次转向之前要请求的页面。我想这点,大家应该都用过。

  下面我们就看看登录的时候发生了什么,看看登录的具体的流程?也请大家注意我使用的一些术语,因为这些术语再Forms中都有特定的对象,大家之后就可以看到的,很重要。

  1.再浏览器中有个登录窗体,要输入用户名和密码等凭证,通过提交给服务器的ASP.NET网站来审核,检查凭证是否正确。
  2.如果凭证正确,那么就会再服务器端就会创建一个"身份验证票据"。身份验证票据中含有了经过加密的用户信息。
  3.这个票据再服务器端被写入cookie中,然后发送到客户端。
  4.然后用户就被重定向到他们最初请求的URL中。


  注:大家可能会有疑问:最初请求的URL到底保存在哪里?不要担心,现在只要明白上面的流程就OK。
 
  5.上面第4步就是要转向最初请求的URL,假设最初的请求页面是Default.aspx,那么现在就是从登录的页面Login.aspx转向到Default.aspx 页面,此时因为身份验证的票据cookie已经存在于客户端的浏览器中了,此时的转向Default.aspx页面时,实际是再次向服务器端发起了请求,所以正如我们之前所谈到的:每个请求都要从ASP.NET管道中一级级的向后传,要经历ASP.NET的的生命周期:Application_BeginRequest,Application_AuthenticateRequest.....。(希望大家明白)

  但是这次的请求就和第一次我们发起的请求步同了,为什么?

  第一次我们请求Default.aspx页面的时候,我们根本就没有提供任何的表明我们身份的票据,但是这次我们已经登录了,而且我们的浏览器中已经有了我们的身份验证的票据的cookie,此时在Application_AuthenticateRequest事件中,Forms验证模块就获取表明我们身份cookie,然后就利用cookie中信息填充Context.User。

  验证模块处理完之后就是授权模块起作用了。其实URL授权模块就会利用我们之前填充在Context.User中的信息来验证用户是否被批准访问所请求的资源或者页面。
 
   Forms验证中的API

  实现Forms身份验证之前,我们看看组成Forms验证的API以及相关的类:
  FormsAuthenticationModule:对每个请求进行验证的HTTP模块
  FormsAuthentication:包含在Forms验证中我们常用的方法和属性(很重要的)
  FormsIdentity:Forms验证标识。
  FormsAuthenticationTicket:身份验证的票据,对用户的信息进行加密后的产物,我们一般把它写如cookie中,之前我们谈过了的。

  上面的类在System.Web.Security下。

  下面我们来一一介绍.

  FormsAuthenticationModule
  它是一个实现了IHttpModule接口的类。它可以用来处理每个请求的Application_AuthenticateRequest事件。如果发送了的请求中已经包含了cookie信息,那么这个模块就对cookie信息进行解密和解析,然后构造一个GenericPrincipal的类实例填充Context.User,并且也创建一个FormsIdentity的实例。
       注意:当我们在web.config中配置了Forms验证后,那么我们在Application_AuthenticateRequest事件写的代码要是和Forms相关的API。上篇文章谈过了。

  FormsAuthentication类 这个类很重要。

  还有一点注意的就是:因为FormsAuthentication和FormsAuthenticationModule名称很相似,很容易混淆。

  它们之前的区别在于,FormsAuthenticationModule是一个HTTP模块;而FormsAuthenticate是一个类,它有很多的方法和属性。更加直白的说就是:它们之前没有什么关联,只是在Application_AuthenticateRequest事件中我们常常要调用FormsAuthenticate类的一些方法和属性。而且FormsAuthenticate的很多方法都是静态的方法,我们不会创建FormsAuthenticate类的实例。

  还有一点要特别注意的就是FormsAuthenticate的Authenticate方法。
我们之前说过了,我们一般是在登录窗体中提交用户信息,然后服务器端验证提交的信息,我们在服务器端常常是去数据库中检查这些信息的正确性,但是去数据库或者其他的数据存储(如文件,活动目录)中去检查只是一种情况。
还有另外的情况。不知道大家是否记得web.config 中的一个配置的节点:

  如果我们在配置文件配置了上述的信息,那么我们就可以用Authenticate方法来检查提供了用户信息(用户名和密码)是否正确,如果我们没有在web.config配置用户的信息,也就是说我们是把信息保存在数据库等其他的地方,那么我们就不能Authenticate这个方法。当然我们很少用Authenticate这个方法,因为我们不可能把所有用户信息硬编码到配置文件中,但是还是要清楚这个方法。
 
  另外我简单的介绍一些常用的方法,具体的使用我以后会讲述。
在FormsAuthenticate中使用频繁的是RedirectFromLoginPage方法。每当验证了用户的凭证后就会使用到这个方法,也就是我们之前说过的:跳转到我们最初请求的页面。
这个方法就这么简单的一"跳",但是其实在内部做了很多的事情:
  1.为用户创建一个身份验证的票据
  2.对身份验证的票据进行加密
  3.创建一个cookie,把加密的票据保存在cookie中
  4.向HTTP响应添加cookie,并且发送给客户端。
  5.跳转,并且把用户重定向到最初请求的页面

  另外FormsAuthenticate类还有很多的其他方法和属性:
  FormsAuthenticate中涉及到客户端保存cookie的两个属性就是:
  FormsCookieName:获取或者设设置cookie的名称
  FormsCookiePath:获取或者设置cookie的url路径
  其中FormsCookiePath属性有一点要注意:大多数的浏览器会在判断cookie是否要和请求一起发送时,用到cookie路径。(我们一般在配置文件配置path="/"),如果我们配置的path不是"/",那么这个cookie就不会和请求发送到服务器端.
FormsAuthenticate中和cookie操作相关的方法有:
  Decrypt:提取身份验证cookie的加密信息,创建FormsAuthenticationTicket,也就是解密。
  Encrypt:加密。从FormsAuthenticationTicket中获取信息,并且加密。以备我们之后把加密的信息写入cookie
  GetAuthCookie:创建身份验证cookie,但是并不把它立即添加到HTTP响应中
  SetAuthCookie:创建身份验证cookie,并且把它添加到Response.Cookie中。
  RenewTicketIfOld:刷新身份验证cookie的生命周期

  GetRedirectUrl:把用户重定向到他们最初请求的页面。
       SignOut:使得当前的身份验证cookie过期。我们常用的注销功能。
 
  FormsIdentity
  大家现在应该知道什么是标识 Identity,它包含了用户名和ID标识信息,可以参看我前面的文章。

  FormsAuthenticationTicket 票据
  通过上面的讲解,大家已经对它不陌生了,FormsAuthenticationTicket实际上就包含用户信息的一个类的实例。
注意:FormsAuthenticationTicket和cookie之间的区别:
       cookie其实就是一个载体,容器,它包含了加密后的FormsAuthenticationTicket。

  FormsAuthenticationTicket类的UserName属性就是用户的用户名,我们可以根据这个属性识别不同的用户。
由于身份验证是基于cookie的,所以要考虑到cookie的过期的问题。比如我们在登录时有个"记住我"的checkbox,如果勾上,那么就创建了一个永不过期的cookie,处于安全,我不提倡这样。

  所以在FormsAuthenticationTicket也提供了关于设置cookie属性:
  Expiration:获取一个表示cookie期满的DateTime对象
  Expired:判断cookie是否过期
  IsPersistent:是否在用户关闭浏览器后继续保存cookie
  IssueDate:返回最初设置cookie的时间

  还有就是CookiePath:设置cookie的保存路径,前面谈论过了,一般设置为"/"。
  另外FormsAuthenticationTicket身份验证票据目的是识别用户。同时,我们也可以利用FormsAuthenticationTicket的UserData属性添加额外的信息,如角色等,然后这额外的信息就可以保存在cookie中。

今天就谈这里。大家先有个总体的认识,具体的代码部分,我们后面谈。谢谢各位!!!

目录
相关文章
|
5月前
|
机器学习/深度学习 JSON 测试技术
CNN依旧能战:nnU-Net团队新研究揭示医学图像分割的验证误区,设定先进的验证标准与基线模型
在3D医学图像分割领域,尽管出现了多种新架构和方法,但大多未能超越2018年nnU-Net基准。研究发现,许多新方法的优越性未经严格验证,揭示了验证方法的不严谨性。作者通过系统基准测试评估了CNN、Transformer和Mamba等方法,强调了配置和硬件资源的重要性,并更新了nnU-Net基线以适应不同条件。论文呼吁加强科学验证,以确保真实性能提升。通过nnU-Net的变体和新方法的比较,显示经典CNN方法在某些情况下仍优于理论上的先进方法。研究提供了新的标准化基线模型,以促进更严谨的性能评估。
144 0
|
4月前
|
开发框架 JSON .NET
|
5月前
|
JSON 数据格式 微服务
.NET下 支持大小写不敏感的JSON Schema验证方法
有很多应用程序在验证JSON数据的时候用到了JSON Schema。 在微服务架构下,有时候各个微服务由于各种历史原因,它们所生成的数据对JSON Object属性名的大小写规则可能并不统一,它们需要消费的JSON数据的属性名可能需要大小写无关。 遗憾的是,目前的JSON Schema没有这方面的标准,标准中都是大小写敏感的。在类似上述情况下,这给使用JSON Schema进行数据验证造成了困难。
|
6月前
|
开发框架 JavaScript .NET
Asp.Net就业课之三验证控件
Asp.Net就业课之三验证控件
69 0
|
开发框架 JSON 算法
ASP.NET Core Web API之Token验证
ASP.NET Core Web API之Token验证
252 0
|
前端开发 JavaScript .NET
一起谈.NET技术,ASP.NET MVC2实现分页和右键菜单
  右键菜单非常方便,很多时候会用到。这篇文章将使用一个JQUERY的插件在asp.net mvc中实现右键菜单。本文还将介绍一下在asp.net mvc中如何实现简单的分页。效果如下图:   首先,下载此插件。
1010 1
|
存储 缓存 .NET
一起谈.NET技术,提高ASP.NET应用程序性能的十大方法
  一、返回多个数据集   检查你的访问数据库的代码,看是否存在着要返回多次的请求。每次往返降低了你的应用程序的每秒能够响应请求的次数。通过在单个数据库请求中返回多个结果集,可以减少与数据库通信的时间,使你的系统具有扩展性,也可以减少数据库服务器响应请求的工作量。
1227 0
|
.NET
一起谈.NET技术,ASP.NET 4.0 一些隐性的扩展
  ASP.NET 4.0在很多方面都做了改进,在这篇ASP.NET 4.0白皮书就描述了很多ASP.NET 4.0的机制改变和改进。在我的博客中,也有几篇关于ASP.NET4.0的特性修改的文章。但是作为一个全新的框架和运行时,内部肯定还会有很多API和扩展点不会暴露的那么明显。
847 0
|
XML 前端开发 .NET
一起谈.NET技术,ASP.NET MVC 2生成动态表单的一种最简单的思路
  在BPM、OA等系统中,都会存在一个表单设计器。有些是通过操作gridview来完成一个表单的设计;有些是通过类似VS拖拽的方法完成一个表单的设计。很明显后面一种优越于前面一种。无论是哪种,最后都会产生一些XML之类的表单结构的数据。
1309 0
|
Web App开发 .NET 数据安全/隐私保护
一起谈.NET技术,ASP.NET身份验证机制membership入门——项目
  前面说了很多关于membership的内容,感觉内容有点凌乱,内容都是一个个知识点,下面我们通过一个小的项目,来把所有的相关内容串一下。   首先描述一下需求:   我们要做一个最简单的网站。有三类用户:匿名用户,员工,管理员,网站结构如下:        admin目录下的页面只允许admin角色的用户访问,employee目录下的页面只允许emp角色的用户访问。
1106 0