min10

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

一.概念
在网站中一般都要涉及到用户身份的验证和管理,网站中的用户管理主要分为四个主要部分,分别是用户身份的验证,用户访问权限的验证,用户的管理,用户的角色管理。
   以往在写用户验证和管理功能的时候,一般都是由开发人员自己通过SESSION或COOKIE取得用户的身份标识,并到数据库中进行查询进行用户身份的验证。在ASP.NET 2.0 中微软为网页程序的用户验证提供了多种方式,可通过配置文件设置验证的方式。一般主要使用的是WINDOWS验证方式和Form验证方式。
   Windows验证方式有多种验证技术,但实质上都是对访问服务器资源的请求进行验证,查看请求的头部信息中是否包含用户的身份信息。当采用Windows验证方式时,如果服务器接收到一个不含有用户信息的请求时,服务器会在返回浏览器的信息中标明要求进行验证。浏览器在此情况下会自动弹出远程用户登录的对话框,要求用户输入其在服务器上的用户名和密码,或是域中的用户名和密码。该种验证方式只能适用于只在内部局域网中运行的网络应用程序。windows验证方式下又分为几种验证方式,分别是基本验证,摘要验证,和windows集成验证。如果使用windows集成验证,则浏览器自动在发送请求时,自动提供用户登录网络的身份标识,避免了用户输入用户名和密码的步骤。
    Form验证方式适用于大型的网站,因为在Form验证方式下,当服务器接收到未含有用户身份标识的请求时,自动将该用户引导到系统登录界面。用户输入用户名和密码后,通过访问数据库等验证方式,验证该用户是否为本网站的合法用户。如果用户通过验证,则ASP.NET为该用户生成窗体验证标签,并将该标签发回到客户端。该标签一般存储到COOKIE中或嵌入到URL中。当用户访问该网站的其他网页时,浏览器会自动提交该标签到服务器,用以记住该用户。
   ASP.NET2.0中的用户身份验证和用户权限验证分别是用两个内置的HTTPMODULE实现的,它们用于验证客户端发送的每一个对该网站资源的请求。用户身份验证模块验证浏览器提供的用户身份标签,如果该请求没有附带用户身份的标签,则用户身份验证模块将该用户标识为匿名用户;用户权限验证用于验证该用户是否有访问指定资源的权限,如果没有权限,则拒绝该请求,并交由用户身份验证模块处理,身份验证模块会将该用户引导到登录界面,要求用户提供具有访问权限的身份标识。
   ASP.NET2.0中的用户权限验证同样也分为两种方式,适用于Windows验证方式的文件验证方式和适用于Form验证方式的URL验证方式。文件验证方式是通过存取控制列表(ACL)确定不同的WINDOWS账户对不同的文件的存储权限。URL验证方式使用WEB.CONFIG决定不同的用户和角色对网站中不同的资源的访问权限。
   在ASP.NET2.0之前,一般的用户管理和角色管理都要靠开发人员定义数据库中关于用户管理和角色管理的数据表,并自己编写代码实现用户登录,新增用户,增加角色,管理用户和角色的后台数据库操作代码。ASP.NET2.0中提供了MEMBERSHIP框架,用于对用户账号的管理。 MEMBERSHIP的优点在于该框架提供了一套用于管理用户账号的接口,但是具体的数据访问和存储操作,却通过PROVIDER来实现,并可根据开发人员的需要配置不同的PROVIDER,用以实现对不同数据源的操作。 ASP.NET自带了两个PROVIDER,分别用于对ACTIVE DIRECTORY,和SQL SERVER的存储访问。角色管理也同样采用这种方式,并自带了若干PROVIDER,分别用于对ACTIVE DIRECTORY,和SQL SERVER的存储访问以及根据用户在WINDOWS中的组来进行角色管理(用于WINDOWS验证模式下)

二.实践

IIS 身份验证

ASP.NET 身份验证分为两个步骤。首先,Internet 信息服务 (IIS) 对用户进行身份验证,并创建一个 Windows 令牌来表示该用户。IIS 通过查看 IIS 元数据库设置,确定应该对特定应用程序使用的身份验证模式。如果 IIS 配置为使用匿名身份验证,则为 IUSR_MACHINE 帐户生成一个令牌并用它表示匿名用户。然后,IIS 将该令牌传递给 ASP.NET。

其次,ASP.NET 执行自己的身份验证。所使用的身份验证方法由 authentication 元素的 mode 属性指定。以下身份验证配置指定 ASP.NET 使用 FormsAuthenticationModule 类:

<authentication mode="Forms" />


注 由于窗体身份验证不依赖于 IIS 身份验证,因此如果要在 ASP.NET 应用程序中使用窗体身份验证,则应该在 IIS 中为应用程序配置匿名访问。

 

 

ASP.NET 窗体身份验证

ASP.NET 窗体身份验证在 IIS 身份验证完成后发生。可以使用 forms 元素配置窗体身份验证。

窗体身份验证配置

以下配置文件片段显示窗体身份验证的默认属性值。

<system.web>
  <authentication mode="Forms">
    <forms loginUrl="Login.aspx"
           protection="All"
           timeout="30"
           name=".ASPXAUTH"
           path="/"
           requireSSL="false"
           slidingExpiration="true"
           defaultUrl="default.aspx"
           cookieless="UseDeviceProfile"
           enableCrossAppRedirects="false" />
  </authentication>
</system.web>


下面是对默认属性值的描述:


 loginUrl 指向应用程序的自定义登录页。应该将登录页放在需要安全套接字层 (SSL) 的文件夹中。这有助于确保凭据从浏览器传到 Web 服务器时的完整性。
 

 protection 设置为 All,以指定窗体身份验证票的保密性和完整性。这导致使用 machineKey 元素上指定的算法对身份验证票证进行加密,并且使用同样是 machineKey 元素上指定的哈希算法进行签名。
 

 timeout 用于指定窗体身份验证会话的有限生存期。默认值为 30 分钟。如果颁发持久的窗体身份验证 Cookie,timeout 属性还用于设置持久 Cookie 的生存期。
 

 name 和 path 设置为应用程序的配置文件中定义的值。
 

 requireSSL 设置为 false。该配置意味着身份验证 Cookie 可通过未经 SSL 加密的信道进行传输。如果担心会话窃取,应考虑将 requireSSL 设置为 true。
 

 slidingExpiration 设置为 true 以执行变化的会话生存期。这意味着只要用户在站点上处于活动状态,会话超时就会定期重置。
 

 defaultUrl 设置为应用程序的 Default.aspx 页。
 

 cookieless 设置为 UseDeviceProfile,以指定应用程序对所有支持 Cookie 的浏览器都使用 Cookie。如果不支持 Cookie 的浏览器访问该站点,窗体身份验证在 URL 上打包身份验证票。
 

 enableCrossAppRedirects 设置为 false,以指明窗体身份验证不支持自动处理在应用程序之间传递的查询字符串上的票证以及作为某个窗体 POST 的一部分传递的票证。
 

授权配置

在 IIS 中,对所有使用窗体身份验证的应用程序启用异步访问。UrlAuthorizationModule 类用于帮助确保只有经过身份验证的用户才能访问页。

可以使用 authorization 元素配置 UrlAuthorizationModule,如以下示例所示。

<system.web>
  <authorization>
    <deny users="?" />
  </authorization>
</system.web>


使用该设置将拒绝所有未经过身份验证的用户访问应用程序中的任何页。如果未经身份验证的用户试图访问某页,窗体身份验证模块将该用户重定向到 forms 元素的 loginUrl 属性指定的登录页。

窗体身份验证控制流


 用户请求应用程序的虚拟目录下的 Default.aspx 文件。因为 IIS 元数据库中启用了匿名访问,因此 IIS 允许该请求。ASP.NET 确认 authorization 元素包括 <deny users="?" /> 标记。
 

 服务器查找一个身份验证 Cookie。如果找不到该身份验证 Cookie,则用户重定向到配置好的登录页 (Login.aspx),该页由 forms 元素的 LoginUrl 属性。用户通过该窗体提供和提交凭据。有关起始页的信息存放在使用 RETURNURL 作为密钥的查询字符串中。服务器 HTTP 应答如下所示:

302 Found Location:
http://localhost/FormsAuthTest/login.aspx?RETURNURL=%2fFormAuthTest%2fDefault.aspx

 

 浏览器请求 Login.aspx 页,并在查询字符串中包括 RETURNURL 参数。
 

 服务器返回登录页以及 200 OK HTTP 状态代码。
 

 用户在登录页输入凭据,并将该页(包括来自查询字符串的 RETURNURL 参数)发送回服务器。
 

 服务器根据某个存储(如 SQL Server 数据库或 Active Directory 用户存储)验证用户凭据。登录页中的代码创建一个包含为该会话设置的窗体身份验证票的 Cookie。

在 ASP.NET 2.0 中,可以通过成员身份系统执行对用户凭据的验证。Membership 类为此提供了 ValidateUser 方法,如下所示:

if (Membership.ValidateUser(userName.Text, password.Text))
{
    if (Request.QueryString["ReturnUrl"] != null)
    {
        FormsAuthentication.RedirectFromLoginPage(userName.Text, false);
    }
    else
    {
        FormsAuthentication.SetAuthCookie(userName.Text, false);
    }
}
else
{
    Response.Write("Invalid UserID and Password");
}


注 使用 Login Web 服务器控件时,它自动为您执行以下步骤。下文使用了前面提供的代码。
 

 对于经过身份验证的用户,服务器将浏览器重定向到查询字符串中的 RETURNURL 参数指定的原始 URL。服务器 HTTP 应答如下所示:

302 Found Location:
http://localhost/TestSample/default.aspx

 

 重定向之后,浏览器再次请求 Default.aspx 页。该请求包括身份验证 Cookie。
 

 FormsAuthenticationModule 类检测窗体身份验证 Cookie 并对用户进行身份验证。身份验证成功后,FormsAuthenticationModule 类使用有关经过身份验证的用户的信息填充当前的 User 属性(由 HttpContext 对象公开)。
 

 由于服务器已经验证了身份验证 Cookie,因此它允许访问并返回 Default.aspx 页。
 

FormsAuthenticationModule

ASP.NET 2.0 在计算机级 Web.config 文件中定义了一组 HTTP 模块,包括大量身份验证模块,如下所示:

<httpModules>
  ...
  <add name="WindowsAuthentication"
       type="System.Web.Security.WindowsAuthenticationModule" />
  <add name="FormsAuthentication"
       type="System.Web.Security.FormsAuthenticationModule" />
  <add name="PassportAuthentication"
       type="System.Web.Security.PassportAuthenticationModule" />
  ...
</httpModules>


每个请求只能使用一个身份验证模块。所使用的身份验证模块取决于 authentication 元素(通常位于应用程序的虚拟目录中的 Web.config 文件中)指定了哪种身份验证模式。

当 Web.config 文件中包含以下元素时,激活 FormsAuthenticationModule 类。

<authentication mode="Forms" />


FormsAuthenticationModule 类构造一个 GenericPrincipal 对象并将其存储在 HTTP 上下文中。GenericPrincipal 对象保存对一个 FormsIdentity 实例的引用,该实例代表当前经过身份验证的用户。应该允许窗体身份验证为您管理这些任务。如果应用程序有特定要求(例如,将 User 属性设置为一个实现 IPrincipal 接口的自定义类),则该应用程序应该处理 PostAuthenticate 事件。FormsAuthenticationModule 验证了窗体身份验证 Cookie 并创建了 GenericPrincipal 和 FormsIdentity 对象之后,会发生 PostAuthenticate 事件。在该代码中,可以构造一个包装 FormsIdentity 对象的自定义 IPrincipal 对象,然后将它存储在 HttpContext. User 属性中。

注 如果执行了这一操作,还需要设置 Thread.CurrentPrincipal 属性上的 IPrincipal 引用,以确保 HttpContext 对象和该线程指向相同的身份验证信息。

窗体身份验证 Cookie

调用 FormsAuthentication.SetAuthCookie 或FormsAuthentication.RedirectFromLoginPage 方法时,FormsAuthentication 类自动创建身份验证 Cookie。

典型的窗体身份验证 Cookie 中包括以下属性:


 Name。该属性指定 Cookie 的名称。
 

 Value。该属性指定 Cookie 的值。

在典型的窗体身份验证 Cookie 中,该值包含一个经过加密和签名的 FormsAuthenticationTicket 对象的字符串表示形式。该 Cookie 包含以下属性:
 

 Expires。该属性指定 Cookie 的到期日期和时间。仅当代码指示应该颁发一个持久的窗体身份验证 Cookie,窗体身份验证才设置该值。
 

 Domain。该属性指定与 Cookie 关联的域。默认值为 null。


 HasKeys。该属性指出 Cookie 是否有子项。
 
 

 HttpOnly。该属性指定是否可以通过客户端脚本访问该 Cookie。在 ASP.NET 2.0 中,该值始终设置为 true。Internet Explorer 6 Service Pack 1 支持该 Cookie 属性,从而防止客户端脚本从 document.cookie 属性访问该 Cookie。如果尝试从客户端脚本访问该 Cookie,则返回一个空字符串。无论何时用户浏览到当前域中的 Web 站点,该 Cookie 仍然发送至服务器。

注 不支持 HttpOnly Cookie 属性的 Web 浏览器要么忽略该 Cookie,要么忽略该属性,这意味着会话仍然容易受到跨站点脚本的攻击。
 

 Path。该属性指定 Cookie 的虚拟路径。默认值为"/",代表根目录。
 

 Secure。该属性指出 Cookie 是否应该仅通过 HTTPS 连接传输。Secure 属性应设置为 true,以便该 Cookie 可以受 SSL 加密的保护。
 

 Version。该属性指定 Cookie 的版本号。
 

创建身份验证 Cookie

通过 FormsAuthentication 类创建身份验证 Cookie,如下所示。用户经过验证后,FormsAuthentication 类在内部创建一个 FormsAuthenticationTicket 对象,方法是指定 Cookie 名、Cookie 版本、目录路径、Cookie 颁发日期;Cookie 到期日期、是否应该保留 Cookie,以及用户定义的数据(可选)。

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
        "userName",
        DateTime.Now,
        DateTime.Now.AddMinutes(30), // value of time out property
        false, // Value of IsPersistent property
        String.Empty,
        FormsAuthentication.FormsCookiePath);
 


接下来,如果 forms 元素的 protection 属性设置为 All 或 Encryption,则窗体身份验证使用 Encrypt 方法对窗体身份验证票进行加密和签名。

string encryptedTicket = FormsAuthentication.Encrypt(ticket);
 


以下文本显示了当 protection 属性设置为 All 时使用的过程:


 创建序列化窗体身份验证票。创建票证的字节数组表示形式。
 

 对窗体身份验证票进行签名。字节数组的消息身份验证代码 (MAC) 的值,由使用 machineKey 元素的 validation 和 validationKey 属性指定的算法和密钥进行计算。默认情况下,使用 SHA1 算法。
 

 对窗体身份验证票进行加密。已经创建的第二个字节数组使用 FormsAuthentication 类的 Encrypt 方法进行加密。该 Encrypt 方法在内部使用由 machineKey 元素上的 decryption 和 decryptionKey 属性指定的算法和密钥。ASP.NET 1.1 版在默认情况下使用 3DES 算法。ASP.NET 2.0 版在默认情况下使用 Rinjdael (AES) 算法。
 

 根据需要创建 HTTP Cookie 或查询字符串。然后,如果窗体身份验证针对 cookieless 身份验证进行了配置,则加密的身份验证票添加到 HttpCookie 对象。使用以下代码创建该 Cookie 对象:

HttpCookie authCookie = new HttpCookie(
                            FormsAuthentication.FormsCookieName,
                            encryptedTicket);

 

 将窗体身份验证Cookie 设置为安全的。如果窗体身份验证票配置为使用 SSL,则 HttpCookie.Secure 属性设置为 true。这表明浏览器仅通过 HTTPS 连接发送 Cookie。

authCookie.Secure = true;

 

 设置 HttpOnly 位。在 ASP.NET 2.0 中,始终设置该位。
 

 设置适当的 Cookie 属性。如果需要,设置 Cookie 的 path、domain 和 expires 属性。
 

 将 Cookie 添加到 Cookie 集合。将身份验证 Cookie 添加到要返回给客户端浏览器的 Cookie 集合。

Response.Cookies.Add(authCookie);

 

每次在身份验证之后接收一个后续请求时,FormsAuthenticationModule 类都会从身份验证 Cookie 中检索身份验证票,对其进行解密,计算哈希值,并比较该 MAC 值,以帮助确保该 Cookie 未被篡改。最后,验证该窗体身份验证票中包含的到期时间。

注 ASP.NET 并不依赖于 Cookie 的到期日期,因为该时间很容易伪造。

角色授权

在 ASP.NET 2.0 中,角色授权已经得到简化。对用户进行身份验证或者将角色细节添加到身份验证 Cookie 时,不再需要检索角色信息。.NET Framework 2.0 包括一个角色管理 API,它使您能够创建和删除角色,将用户添加到角色以及从角色删除用户。该角色管理 API 将其数据存储在一个基础数据存储中,它通过针对该数据存储的适当角色提供程序访问该存储。以下角色提供程序为 .NET Framework 2.0 附带,可以与窗体身份验证一起使用:


 SQL Server。它是默认的提供程序,将角色信息存储在 SQL Server 数据库。
 

 授权管理器 (AzMan)。 该提供程序使用 XML 文件、Active Directory 或 Active Directory 应用程序模式 (ADAM) 中的一个 AzMan 策略存储作为其角色存储。它通常用于 Intranet 或 Extranet 方案中,其中 Windows 身份验证和 Active Directory 用于进行身份验证。
 

有关如何使用角色管理 API 的详细信息,请参阅 How To: Use Role Manager in ASP.NET 2.0。

 

 

Cookieless 窗体身份验证

ASP.NET 2.0 支持 cookieless 窗体身份验证。该功能由 forms 元素的 cookieless 属性控制。该属性可以设置为以下四个值之一:


 UseCookies。该值强制 FormsAuthenticationModule 类使用 Cookie 传输身份验证票。
 

 UseUri。该值指示 FormsAuthenticationModule 类重写 URL 来传输身份验证票。
 

 UseDeviceProfile。该值指示 FormsAuthenticationModule 类查看浏览器功能。如果浏览器支持 Cookie,则使用 Cookie;否则,重写 URL。
 

 AutoDetect。该值通过一个动态检测机制指示 FormsAuthenticationModule 类检测浏览器是否支持 Cookie。如果检测逻辑表明不支持 Cookie,则重写 URL。
 

如果应用程序配置为使用 cookieless 窗体身份验证,并且正在使用 FormsAuthentication.RedirectFromLoginPage 方法,则 FormsAuthenticationModule 类自动设置 URL 中的窗体身份验证票。以下代码示例显示了典型 URL 在重写后的外观:

http://localhost/CookielessFormsAuthTest/(F(-k9DcsrIY4CAW81Rbju8KRnJ5o_gOQe0I1E_jNJLYm74izyOJK8GWdfoebgePJTEws0Pci7fHgTOUFTJe9jvgA2))/Test.aspx


括号中的 URL 部分包含 Cookie 通常将包含的数据。该数据在请求处理过程中由 ASP.NET 删除。该步骤由 ASP.NET ISAPI 筛选器执行,而不是在 HttpModule 类中执行。如果从一个 .aspx 页读取 Request.Path 属性,您在 URL 中不会看到任何额外的信息。如果重定向请求,URL 将自动重写。

注 难以保证 URL 中包含的身份验证票的安全。当安全性极为重要时,您应该使用 Cookie 存储身份验证票。

 

 

成员身份和登录控件

ASP.NET 2.0 引入了成员身份功能和一组登录 Web 服务器控件,它们简化了使用窗体身份验证的应用程序的实现。

成员身份为应用程序用户提供凭据存储和管理。它还提供一个成员身份 API,可以在使用窗体身份验证时简化用户凭据的验证任务。该成员身份功能构建于提供程序模型之上。该模型允许实现和配置指向不同用户存储的不同提供程序。ASP.NET 2.0 包括以下成员关系提供程序:


 Active Directory 成员关系提供程序。该提供程序使用 Active Directory 或 Active Directory 应用程序模式 (ADAM) 用户存储。
 

 SQL Server 成员关系提供程序。该提供程序使用 SQL Server 用户存储。
 

还可以添加对自定义用户存储的支持。例如,可以添加对其他轻量级目录访问协议 (LDAP) 目录或其他现有公共标识存储的支持。为此,创建一个从 MembershipProvider 抽象基类继承的自定义提供程序。

ASP.NET 登录控件自动使用成员身份和窗体身份验证,并封装提示用户输入凭据,验证用户,恢复或替换密码等所需的逻辑。实际上,ASP.NET 登录控件在窗体身份验证和成员身份上提供一个抽象层,并且取代了您使用窗体身份验证时通常必须进行的大多数或全部工作。

原文链接:http://edu.itbulo.com/200607/101618.htm

posted on 2008-11-03 12:13  min10  阅读(323)  评论(0编辑  收藏  举报