ASP.NET Internet安全Forms身份验证 指南(上)
广告投放★自助友情CMS落伍广告联盟晒乐广告联盟脉动广告联盟品味广告联盟
广告位可自定样式联系QQ:4285248个文字广告月20元广告联系QQ:428524广告位可自定样式
8个文字广告月20元黄金广告位每月20元广告位可自定样式联系QQ:428524广告位可自定样式
左旋肉碱、全国包邮
买二送一、无效退款

文章浏览→编程相关.Net编程→ASP.NET Internet安全Forms身份验证 指南(上)

ASP.NET Internet安全Forms身份验证 指南(上)
ASP.NET Internet安全Forms身份验证 指南(上)

ASP.NETInternet安全Forms身份验证指南

作者:不及格的程序员-八神

摘要

 

安全性是 ASP.NET Web应用程序中一个非常重要的方面,它涉及内容非常广泛,不能在一篇文章内说明所有的安全规范,本文讲述如何利用IIS以及Forms 身份验证构建安全的 ASP.NET 应用程序,它是目前被使用最多最广的验证/授权方式.

本文分别以ASP.NET1.1ASP.NET2.0Forms 身份验证上的实现方法,以及ASP.NET2.0较上一版本有哪些改进或变化进行说明.相信读者都己经看过许多类似这样的文章,不伦是在网上或是某些专业书籍上,最近又有模式&实践小组成员发布WCF安全模型指南,可见构建网站安全总是不过时的话题,作者认为此文也绝对是您应该收藏的参考资料.

 

ASP.NET安全性的工作原理

网站在安全性方面有一个常见的要求:特定的页面仅允许某些成员或其他经过身份验证的用户浏览.充分利用Forms身份验证是最好的方式.

身份验证

从实现机制来说ASP.NET1.1与ASP.NET2.0的安全模型是一致的.首先配置网站为Forms身份验证模式,之后用户访问网站的URL,Forms身份验证系统会将未经身份验证的请求重定向到指定的登录页.用户输入凭据(用户名密码)并提交该页.如果验证程序验证用户的身份合法,则系统会向客户端发出一个特定Cookie(.NET1.1不支持无Cookie模式),它代表用户的身份验证票据.这样后续的请求中,客户端浏览器会把该Cookie一同发送致服务器,如果该Cookie有效则用户通过身份验证并允许对原始请求的资源的访问.

授权

如果用户的请求被验证通过了,但是他请求的URL是否允许用户访问了呢,这就用到了授权.可以通过应用程序配置文件来进行授友也可以在程序中使用代码来验证用户是否有资格访问该资源.如果授权失败,则ASP.NET 将用户重定向到登录页.如果用户已被授权,则将允许用户访问受保护资源.

ASP.NET1.1实现方式

 ASP.NET1.1的实现方式非常简单,不过我们还是需要手写一些代码的,下面我们就一步一步地实现.应用程序配置节的详细说明请参考MSDN相关文档.

l        配置应用程序使用 Forms身份验证,编辑web.config文件

<configuration>
 <system.web>

<authenticationmode="Forms">
<formsname=".ASPXCOOKIEAUTH" loginUrl="
Login.aspx"protection="All" timeout="30" path="/" />
</authentication>
<authorization>

<denyusers="?"/><!拒绝匿名-->
</
authorization>
......

</system.web>

<locationpath="Admin"><!配置授权,只允许拥有Admins角色的用户访问这个目录下的文件(*.aspx)-->

 <system.web>

      <authorization>

           <allow roles="Admins"/><!虽然下面配置为拒绝所有用户,但是allow的优先级比deny高.-->

           <deny users="*"/><!拒绝所有用户-->

<!

一个用户或角色必须特别指定为拒绝,才能拒绝该用户或角色对URL的权限.如果上面的示例没有指定<denyusers="*" />元素,则将允许所有通过身份验证的用户访问所请求的URL,而不考虑其所属的角色.

-->

      </authorization>

    </system.web>

 </location>

</configuration>

l        创建登录页面Login.aspx

页面预览如下,代码详细参考本文附件的项目源码.

l        创建用户身份主体

ASP.NET1.1安全模型提供了四种授权方法,这四种方法都使用HttpContext.User对象进行验证授权.

l         使用应用程序配置进行授权,只有具有指定角色的用户才能访问web.config所在的文件夹与子文件夹

<authorization>

        <allow roles="Admins"/>

        <deny users="?"/>

</authorization>

l         使用PrinciplePermissionAttribute控制对类和方法的访问,只允许角色为Admins的成员才能调用该方法

[System.Security.Permissions.PrincipalPermission(System.Security.Permissions.SecurityAction.Demand,Role=”Admins”)]

public static bool MethodName()

{

        ...

}

l         以编程方式使用PrinciplePermission类控制对代码块的访问,只允许角色为Admins的成员调用Demand之后的代码

public static bool MethodName()

{

        System.Security.Permissions.PrincipalPermission perm = newSystem.Security.Permissions.PrincipalPermission(null,"Admins");

        perm.Demand();

        ...

}

l        使用Iprincipal.IsInRole方法,只允许角色为Admins的成员运行if中的代码,大部分情况我们都使用这种方法判断用户是否有权限.

public static boolMethodName()

{

      if (HttpContext.Current.User.IsInRole("Admins"))

      {

             //some code

      }

}

针对以上的特点,程序员必须在合适的地方创建HttpContext.User对象,以达到验证模型的要求.开发人员必须编写HttpApplication::AuthenticateRequest事件.该事件的发生代表着用户己经通过Forms身份验证.

Global.asax中实现Application_AuthenticateRequest.

        protectedvoidApplication_AuthenticateRequest(Object sender, EventArgse)

        {

             HttpApplication app = (HttpApplication)sender;

             HttpCookie cookie =Request.Cookies[FormsAuthentication.FormsCookieName];

             if (cookie !=null)

             {

                  stringencryptedTicket = cookie.Value;

                  FormsAuthenticationTicket ticket =FormsAuthentication.Decrypt(encryptedTicket);

                  //获取在登录验证时加入验证票据的用户所拥有的角色,但真正开发时请不这样做,建议从数据库中获取该用户角色信息.

                  //因为Cookie本身有长度的限制,并且将用户角色存储到客户端也不是安全的行为.

                  //大家想想如果Cookie不限制大小,那么它的尺寸大到几MB或GB时,客户端与服务器的每一次通迅,将是怎样的一种情况了,呵呵.

                  //这里仅展示如何将角色信息加入到用户主体GenericPrincipal中.

                  string[] roles =ticket.UserData.Split(newchar[] { ','});//获取角色

                  FormsIdentity identity = new FormsIdentity(ticket);

                  System.Security.Principal.GenericPrincipal user = newSystem.Security.Principal.GenericPrincipal(identity,roles);

                  app.Context.User = user;

                  //app.Context.User =new System.Security.Principal.GenericPrincipal(newSystem.Web.Security.FormsIdentity(FormsAuthentication.Decrypt(cookie.Value)),new string[]{"Admins"});

             }

}

或者在Global.asax中实现FormsAuthentication_Authenticate效果是一样的.

voidFormsAuthentication_OnAuthenticate(objectsender, FormsAuthenticationEventArgse)

       {

             HttpCookie cookie =Request.Cookies[FormsAuthentication.FormsCookieName];

             if (cookie !=null)

            {

                  stringencryptedTicket = cookie.Value;

                  FormsAuthenticationTicket ticket =FormsAuthentication.Decrypt(encryptedTicket);

                  string[] roles =ticket.UserData.Split(newchar[] { ',' });

                  FormsIdentity identity = new FormsIdentity(ticket);

                  System.Security.Principal.GenericPrincipal user = newSystem.Security.Principal.GenericPrincipal(identity,roles);

                  e.Context.User =user;              

             }

       }

其实FormsAuthenticationModule会自动生成一个User对象,只不过这个对象的角色列表为空,它只能是代表通过身份验证,而不能通过授权,因为我们限制了目录的访问角色,所以开发人员必须实现上面代码,才能满足我们的要足,如果说你的网站仅需要通过身份验证的话,就可不必实现这些方法了.

        用户在请求URL时,ASP.NET请求通道会连续触发一堆的事件,这些事件完成了一系列任务,其中就包括Forms身份验证事件与授权事件.如下所示:

                  BeginRequest 请求开始事件

AuthenticateRequest 验证通过事件 (上面两段代码就是在这个事件中被执行)

PostAuthenticateRequest 用户标识己建立时发生 ASP.NET 2.0引入的事件,后面会讲到.

AuthorizeRequest 当安全模块已验证用户授权时发生

....其它事件略;

                  正是这些事件的垒加促成了ASP.NET框架验证模型的实现, 而且通过完成上面的几个步骤,网站内容就己经受到授权机制的保护了.

下面让我们看看ASP.NE安全模型是如何做到授权的.

l         ASP.NET 1.1 安全模型验证授权的原理

在 ASP.NET中,有两种方式限制对资源访问的权限:文件授权与URL 授权,这里我们仅讨伦后者.
URL 授权由 UrlAuthorizationModule 执行,它将用户和角色映射到 ASP.NET 应用程序中的URL.这个模块可用于有选择地允许或拒绝特定用户或角色对应用程序的任意部分(通常在web.config文件中为目录指定授权用户或角色)的访问权限.

HTTP模块是在ASP.NET框架默认应用程序配置文件中注册的,如下:

下面简单分析UrlAuthorizationModule的源码,便可了解验证模型是如何验证在web.config中指定的授权规则.

UrlAuthorizationModule在应用程序初始化时向HttpApplication::AuthorizeRequest事件(安全模块已验证用户授权时发生)注册委托代码,该代码内部调用AuthorizationConfig::IsUserAllowed.方法实现截图如下:

上面代码又调用了AuthorizationConfigRule::IsUserAllowed方法,截图如下:

由于HttpApplication::AuthorizeRequest事件是在HttpApplication::AuthenticateRequest事件之后执行的(请看我提到过的事件列表),在前面介绍的AuthenticateRequest事件中我们修改了Context.User对象,而且加入了角色信息,所以AuthorizeRequest事件在验证用户的权限时发现Context.User对象中什么都有,所以它才允许用户访问请求的资源,否则请求将被返回到指定的页面.以上就是ASP.NET1.1的原理,怎么样你理解了吗?

ASP.NET2.0你仍可以用这样的机制,但又增加新特性.下面就看看在ASP.NET2.0中是如何实现的吧!

 

所属分类:编程相关.Net编程    作者:荡凯网络    时间:2010-7-18 17:37:00

文章导航