第18章 给我的程序加把锁——ASP.NET安全策略
本章视频教学录像:24分钟
由于网络上的资源是开放的,所以面对不同的用户,保护自己的资源不被盗用和破坏是在程序设计过程中必须要考虑的问题,也是程序员最关注的问题之一。本章介绍ASP.NET中的身份验证机制和登录控件的使用。
本章要点(已掌握的在方框中打钩)
□ ASP.NET安全机制综述
□ ASP.NET Forms 身份验证机制
□ ASP.NET Windows 身份验证机制
□ ASP.NET Passport 身份验证机制
□ ASP.NET 现有登录控件配置及使用
18.1 ASP.NET安全机制综述
本节视频教学录像:4分钟
我们开发的程序不仅要实现预定的功能,更要有安全保证机制。如果一个财务程序涉及真金白银的增删改查操作,而安全机制不过关,后果可想而知。可以说,如果没有完善的安全机制作保证,功能再强大的程序都是徒劳,甚至可以不客气地说:没有安全保障,很多系统还不如不开发。安全问题由来已久,系统在开发前首先要定好的就是安全认证机制及其详细的权限设定。
身份验证是一个验证客户端身份的过程,通常采用指定的第三方授权方式。客户端可能是最终用户、计算机、应用程序或服务。客户端的标识称为安全原则。为了使用服务器应用程序进行验证,客户端提供某种形式的凭据来允许服务器验证客户端的标识。确认了客户端的标识后,应用程序可以授予进行操作和访问资源的原则。
ASP.NET 提供有 3 种类型的权限认证方式,即 Forms、Passport 和 Windows,如图所示。在Visual Studio 2008中新建了一个Website,默认是使用Windows认证方式。
如果应用程序使用 Active Directory 用户存储,则应该使用集成 Windows 身份验证。ASP.NET 应用程序使用集成 Windows 身份验证时,最好的方法是使用 ASP.NET 的 Windows 身份验证提供程序附带的 Internet 信息服务 (IIS) 身份验证方法。使用该方法,将自动创建一个 WindowsPrincipal 对象(封装一个 WindowsIdentity 对象)来表示经过身份验证的用户,您无需编写任何身份验证特定的代码。
ASP.NET 还支持使用 Windows 身份验证的自定义解决方案(避开了 IIS 身份验证)。例如,可以编写一个根据 Active Directory 检查用户凭据的自定义 ISAPI 筛选器。使用该方法,必须手动创建一个WindowsPrincipal 对象。
3种不同的认证方式以及ASP.NET请求响应处理流程如图所示。
IIS 向 ASP.NET 传递代表经过身份验证的用户或匿名用户帐户的令牌,该令牌在一个包含在IPrincipal 对象中的 IIdentity 对象中维护,IPrincipal 对象进而附加到当前 Web 请求线程。可以通过HttpContext.User 属性访问 IPrincipal 和 IIdentity 对象,这些对象和该属性由身份验证模块设置,这些模块作为 HTTP 模块实现并作为 ASP.NET 管道的一个标准部分进行调用,如上图所示。
ASP.NET 管道模型包含一个 HttpApplication 对象、多个 HTTP 模块对象,以及一个 HTTP 处理程序对象及其相关的工厂对象。HttpRuntime 对象用于处理序列的开头。在整个请求生命周期, HttpContext 对象用于传递有关请求和响应的详细信息。
18.2 ASP.NET身份验证机制
本节视频教学录像:9分钟
本节学习ASP.NET提供的3种类型的权限认证机制:Forms身份验证机制、Passport身份验证机制和Windows身份验证机制。
18.2.1 ASP.NET Forms身份验证机制
当某一个用户使用用户名成功登录网站时,FormsAuthentication(窗体身份验证机制,下面统一使用英文术语)将会创建一个authentication ticket (身份验证票),通过这个ticket就可以在网站上全程跟踪这个用户了。Form authentication ticket通常被包含在一个Cookie里面,但是Asp.net也支持不使用Cookie的FormsAuthentication,这个时候ticket就需要通过Query string 传递。
当一个用户登录某个网站时,需要提供身份验证才能进入网站。如果他还没有输入验证信息(通常是用户名和密码),则此用户将会被重定向到一个登录页面。用户可以在登录页面输入验证信息,然后这些信息被发送到服务器与某一个存储用户身份信息的介质(例如Sql Server或者某个文件)进行信息对比。在ASP.Net中,可以通过MemberShip Proivder来访问存储在诸如Sqlserver的信息(Provider模式有很多优点,稍后会详细说明)。当用户信息通过验证后,此用户将获得允许,访问他所期望的页面。
FormsAuthentication通过FormsAuthenticationModule这个类来执行,这个类是ASP.net页面运行周期的一部分。下面来解释FormsAuthentication在ASP.net中是如何工作的。
ASP.NET验证分为以下两步。
⑴IIS 验证当前用户访问网站所使用的 windows 账号是否有权限。如果 IIS 访问被配置为anonymous,则任何用户都能访问页面。
⑵IIS 验证完毕,ASP.net 开始执行自身的验证。验证模式可以在 web.config 文件中配置, 只要在config文件中写上 <authentication mode="Forms"/>,那么ASP.net就知道使用FormsAuthenticationModule 类进行验证。
开发ASP.NET项目的过程中,我们最常用的就是Forms认证,也叫表单认证。
下面的实例介绍如何使用ASP.NET中的Forms验证对用户输入数据进行检查,判断证件资料是否正确,也就是身份验证的过程。
【范例18-1】使用ASP.NET Forms身份验证机制。
⑴在 Visual Studio 2010 中,创建名为“HelloForms”的 ASP.NET 空网站,并添加一个 Login. aspx页面。在页面中添加两个TextBox和一个Button控件,分别用于输入用户名和密码以及执行登录操作,如图所示。
控件属性如下。
⑵添加一个Main.aspx页面,当用户输入正确信息时导向该页面。
⑶打开应用程序 HelloForms 的 web.config 文件,把文件中的配置节“authentication”修改为Froms验证方法。并在<authentication>节的<forms>节中配置要使用Cookie名称和登录的URL;在< authorization>节的<deny>中设置为拒绝匿名用户访问资源。程序代码如下。
01 <authentication mode="Forms">
02 <forms name="authCookie" loginUrl="Login.aspx"/>
03 < /authentication>
04 <authorization>
05 <deny users="?"/>
06 < /authorization>
⑷在登录按钮的单击事件中输入以下代码:
01 protected void btnLogin_Click(object sender,EventArgs e)
02 {
03 if (txtUserName.Text== "admin"&& txtPwd.Text== "123")
04 {
05 FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
06 Response.Redirect("Main.aspx");
07 }
08 else
09 {
10 Response.Write("<script>alert('输入有误,请重新输入! ');< /script>");
11 }
12 }
【运行结果】
按【F5】键运行,测试运行结果,如图所示,输入正确的用户和密码导向主页面;输入错误提示重新输入。如果直接运行Main.aspx页面,也会自动导向Login.aspx页面。
【范例分析】
<deny>节设置的作用是拒绝匿名访问,因此直接访问Main.aspx页面就会导向Login.aspx页面;FormAuthentication对象的SetAuthCookie方法用来创建存储用户信息的Cookie。
18.2.2 ASP.NET Windows身份验证机制
Window身份验证方式,是与IIS配合在一起的一种认证方式。在IIS中已经提供了匿名身份验证、Windows 集成的 (NTLM) 身份验证、Windows 集成的 (Kerberos) 身份验证、基本(base64 编码)身份验证、摘要式身份验证以及基于客户端证书的身份验证。
WindowsAuthenticationModule 类负责创建 WindowsPrincipal 和 WindowsIdentity 对象来表示经过身份验证的用户,并且负责将这些对象附加到当前的Web 请求。
对于 Windows 身份验证,应遵循以下步骤。
⑴WindowsAuthenticationModule 使用从 IIS 传递到 ASP.NET 的 Windows 访问令牌创建一个 WindowsPrincipal 对象,该令牌包装在 HttpContext 类的 WorkerRequest 属性中。引发AuthenticateRequest 事件时,WindowsAuthenticationModule 从 HttpContext 类检索该令牌并创建WindowsPrincipal 对象。HttpContext.User 用该 WindowsPrincipal 对象进行设置,它表示所有经过身份验证的模块和 ASP.NET 页的经过身份验证的用户的安全上下文。
⑵WindowsAuthenticationModule 类使用 P/Invoke 调用 Win32 函数,并获得该用户所属的Windows 组的列表,这些组用于填充 WindowsPrincipal 角色列表。
⑶WindowsAuthenticationModule 类将 WindowsPrincipal 对象存储在 HttpContext.User 属性中,随后,授权模块用它对经过身份验证的用户授权。
DefaultAuthenticationModule 类(也是 ASP.NET 管道的一部分)将 Thread.CurrentPrincipal 属性设置为与 HttpContext.User 属性相同的值,它在处理 AuthenticateRequest 事件之后进行此操作。
【范例18-2】使用ASP.NET Windows身份验证机制输出当前计算机名称和账户。
⑴在Visual Studio 2010中,创建名为“HelloWindowsAuthorization”的ASP.NET空网站,并添加Default.aspx页面。
⑵打开应用程序HelloWindowsAuthorization的web.config 文件,把文件中的配置节“authentication”修改为Windows验证方法。程序代码如下。
<authentication mode="Windows">
⑶打开Default.aspx文件的源视图,在form标签对之间添加如下代码。
01 <form id="Form2"method="post" runat="server">
02 欢迎您,<%=User.Identity.Name%>!
03 < /form>
【运行结果】
按【F5】键调试运行,即可在浏览器中输出当前计算机的名称和账户,如图所示。
18.2.3 Passport验证
Passport验证是微软公司提供的一种集中式验证服务,它能够用来验证访问网站或应用程序的用户是否为合法用户。如果用户没有登录或者不是合法用户,Passport验证会提供集中验证方式验证用户的合法性。使用Passport验证时,用户将被重定向到Passport登录网页,该页面提供了一个简单的窗体让用户填写资料信息,该窗体将通过微软公司的Passport服务类检查用户的信息,以确定用户的身份是否有效。
使用Passport验证必须要下载.Net Passport SDK工具包,并进行应用程序的配置,而且必须是微软公司的Passport服务的成员才能使用该服务。这里我们不做过多介绍。
18.3 ASP.NET登录控件全解
本节视频教学录像:8分钟
从ASP.NET开始,用户管理、权限管理等成为一个入门级程序员也可以接触的技术,在大大简化入门门槛的同时,也为使用这套机制的各个站点的安全性提高了一个层次。本节介绍相关各个控件的使用。
18.3.1 ASP.NET登录机制概述
通过之前的操作,已经基本具备了一个网站的结构,但还不是一个动态网站,因为还没有加入动态数据的支持。本节将介绍ASP.NET上的另一组功能强大的控件——登录控件。在ASP.NET平台上,已经自动集成了一套用于进行登录、权限控制的方法,使用这些方法,一个初学者可以轻松地设计一个安全完备的登录验证系统。下面具体介绍这些控件的使用方法。
18.3.2 查看登录控件默认使用的数据库
在管理用户等网站的动态数据前,需要先配置后台数据库,具体操作步骤如下。
⑴启动Microsoft Visual Studio 2010,打开随书光盘中的“Sample\ch18\ 范例18-3\LoginTemplate”网站,选择【网站】【ASP.NET配置】菜单命令,打开网站配置窗口。
⑵选择【安全】选项卡,单击左下角的【选择身份验证类型】按钮,在打开的窗口中选中【通过Internet】单选按钮,然后单击右下角的【完成】按钮。
⑶返回【安全】选项卡,进行用户设置的选项已被激活,允许创建和管理用户。单击左侧的【创建用户】链接,根据系统提示创建一个名为“admin”、密码为“admin_123”的用户(密码中需包含“_”、“!”或“@”等符号中的一个)。
⑷关闭该窗口,返回开发环境,单击【解决方案资源管理器】中的按钮,刷新资源列表,可以看到App_Data节点下增加了一个节点ASPNETDB.MDF,根据其文件扩展名及图标可以看出,这是一个系统自动添加的数据库,而且是在配置了网站用户之后添加的。
⑸双击节点ASPNETDB.MDF,系统自动打开【服务器资源管理器】面板,展开节点“表”,其中已经有了很多表。
⑹右键单击“表”节点下的aspnet_Users,在弹出的快捷菜单中选择【显示表数据】菜单项,可以显示该表中的数据,即前面注册的用户信息。
由以上操作可知,可以选择【网站】【ASP.NET配置】命令,根据验证类型及提供程序等的配置在默认目录App_Data下建立一个数据库,此数据库用于保存所有的账户信息(包括用户名、密码、角色、权限等所有登录控件需要使用的动态配置信息),但这些配置也可以手动更改。
18.3.3 手动更改Visual Studio 2010的默认网站配置
手动更改Visual Studio 2010的默认网站配置的具体步骤如下。
第1步:创建数据库
⑴打开目录“C:\Windows\Microsoft.NET\ Framework\v4.0.30319。
⑵运行此目录下的文件aspnet_regsql. exe,弹出【ASP.NET SQL Server 安装向导】的欢迎界面。
⑶单击【下一步】按钮,设置安装选项,选中【为应用程序服务配置SQL Server】单选按钮。
⑷单击【下一步】按钮,设置服务器和数据库,这里只设置服务器而不选择数据库。在【服务器】文本框中输入本地计算机名称,在【数据库】下拉列表中选择默认的【<默认>】选项。
⑸单击【下一步】按钮,系统提示要安装的服务器名称,以及要安装的数据库名称aspnetdb,这与前面使用的自动生成的数据库同名。
⑹单击【下一步】按钮,稍等片刻,显示成功信息后单击【完成】按钮。
⑺启动SQL Server 2008,在【对象资源管理器】的【数据库】文件夹下,查看是否已有此数据库。
第2步:配置ASP.NET全局数据库信息
⑴返回Visual Studio 2010开发环境,选择【工具】【连接到数据库】命令,弹出【添加连接】对话框,选择刚才设置的服务器,然后设置数据库为“aspnetdb”。
⑵单击【高级】按钮,弹出【高级属性】对话框,复制底部TextBox中的字符,然后单击【取消】按钮,关闭该对话框。
⑶打开【Internet信息服务】窗口,选中IIS服务器名。
⑷在右侧的操作区单击“更改.NET FrameWork版本”,确定ASP.NET的版本为v4.0。
⑸单击【编辑全局配置】按钮,打开【ASP.NET配置设置】对话框,在【常规】选项卡中选中【连接字符串管理器】中的LocalSqlServer。
⑹单击【编辑】按钮,弹出【编辑/添加连接字符串】对话框,将刚才复制的字符串粘贴到【连接参数】文本框中,单击【确定】按钮。
这样的数据库配置会导致以下两个问题。
⑴所有网站的默认权限管理功能都在数据库服务器中指定的一个库中,会导致网站之间的权限管理比较混乱。
⑵不同的网站建设会使用不同类型的数据库管理系统,如Oracle、MySQL等,甚至一个站点会有多个数据库管理系统,这样的统一配置肯定是不合适的。
那么,是不是我们只能接受让系统统一配置成网站指定名称附加在项目中,或统一在数据库中,或者统一使用SQL Server数据库呢?
不是。我们可以在Web.config文件中进行如下配置:
01 <remove name="LocalSqlServer" />
02 <add name="LocalSqlServer" connection String="Data Source=DatabaseServerName;InitialCatalog=DatabaseName;IntegratedSecurity=True"
03 providerName="System.Data.SqlClient" />
第1行的意思是删除.NET平台默认指定的ConnectionString,第2行的意思是建立一个符合自己实际情况的数据库。配置好此字符串后,再运行【ASP.NET网站配置】工具,会在Web.config中指定的数据库位置创建相关的表和逻辑。
18.3.4 使用登录控件
本小节讲解登录控件的具体使用方法。登录控件全部放置在工具箱的【登录】标签下,使用ASP. NET的登录控件可以轻松地实现以下功能。
⑴注册新用户。
⑵登录。
⑶找回密码。
⑷显示客户端用户状况。
⑸根据角色管理用户的访问权限。
第1步:准备工作
⑴启动Microsoft Visual Studio 2008,打开随书光盘中的“Final\ch18\范例18-3\Login Template”网站,选择【网站】【ASP.NET配置】菜单命令,使用ASP.NET配置工具,创建3个用户,即Admin、User、Guest。
⑵在【解决方案资源管理器】窗口中的Logins文件夹下添加两个使用母版页的Web窗体,分别为Change Password.aspx和PasswordRecovery.aspx。
第2步:在母版页中使用LoginView控件
由于用户注册、登录时需要显示当前访客的用户状态,因此开始使用登录、注册控件之前,先介绍访客状态显示的LoginView控件。
⑴在【解决方案资源管理器】窗口中双击MasterPage.master文件,切换到设计视图,将table1的第2列第1个单元格的高度设置为75,第2个单元格的高度设置为25,并将此单元格的对齐方式设置为【居右】。
⑵在table1的第2列第2个单元格中添加一个LoginView控件。
⑶打开 LoginView 任务列表,可以看到 Login View 有两种视图,即 AnonymousTemplate 和LoggedInTemplate。其中,前者是用户未登录,匿名用户时的视图;后者是用户登录后的视图。
⑷切换到AnonymousTemplate视图,在其中插入一个HyperLink控件,将其Text属性设置为“注册”,NavigateUrl属性设置为“~/Logins/Register.aspx”。
⑸切换到LoggedInTemplate视图,在其中输入“欢迎您”,然后在逗号后面插入一个LoginName控件,在此控件后面输入一个句号。
⑹将光标置于LoginView控件之后,输入两个空格,然后在空格之后插入一个Login Status控件。
⑺将LoginView1切换到Anonymous Template视图,插入一个HyperLink控件,将其Text属性设置为“找回密码”,NavigateUrl属性设置为“~/Logins/ Password Recovery. aspx”。
⑻将LoginView切换到LoggedInTemplate视图,插入一个HyperLink控件,Text属性设置为“修改密码”,将其NavigateUrl属性设置为“~/Logins/ChangePassword. aspx”。
⑼按【F5】快捷键运行调试,确认网站可以运行。
从图中可以看到,网站的布局已经发生了变化,这时就需要用前面学过的网站美化技术来解决这一问题。由于篇幅原因,在此不再讲述,读者可以将前面学过的知识在此灵活运用。
第3步:设计登录界面
⑴打开Login.aspx的设计视图,在pageContent中插入一个Login控件。
⑵将其 PasswordLableText 属性设置为“密码 :”,将其 DestinationPageUrl 属性设置为“~/Default.aspx”。
第4步:设计注册界面
⑴打开Register.aspx的设计视图,在pageContent中插入一个CreateUserWizard控件。
⑵将其ContinueButtonText属性设置为“返回首页”,ContinueDestinationPageUrl属性设置为“~/Default.aspx”。
第5步:设计找回密码界面
打开PasswordRecovery.aspx的设计视图,在pageContent中插入一个Password Recovery控件。
第6步:设计修改密码界面
⑴打开ChangePassword.aspx的设计视图,在pageContent中插入一个Change Password控件。
⑵将PasswordLableText属性设置为“原密码”,ConfirmNewPasswordLableText属性设置为“请确认”,再将CancelDestina- tionPageUrl属性设置为“~/Default.aspx”。
【运行结果】
设置Default.aspx页面为起始页,按【F5】快捷键运行网站。单击【登录】超链接,显示登录窗体。
单击【注册】超级链接,显示注册窗体。
单击【找回密码】超级链接,显示找回密码窗体。
至此,未编写任何代码,通过拖曳就完成了一个功能完备而简单的登录、注册管理模块。但是有的时候网站还需要设置访问权限,因此下面讲解ASP.NET提供的权限管理模块。
18.3.5 使用权限管理模块
权限管理模块允许用户基于角色进行管理,也可以直接对单个用户进行管理,这些设置全部存储在数据库中,或者也可以在Web.Config中简单添加。
⑴选择【网站】【ASP.NET配置】菜单命令,在弹出的对话框中选择【安全】选项卡。
⑵单击【启用角色】按钮,此时系统会在Web. config中增加一部分代码。
<roleManager enabled="true"/>
如果前面在【ASP.NET配置设置】对话框中,选中【角色】选项区中的【启用角色管理】复选框,则在ASP.NET配置窗口中的【安全】选项卡中,角色默认被启用,因此没有【启用角色】按钮,只有【禁用角色】按钮。
单击【禁用角色】按钮,Web.config中会增加一部分代码。
<roleManager enabled="false"/>
因此,ASP.NET服务器允许全局配置,也允许网站有自己的配置信息,并且以网站自己的配置信息为主。
所有的全局配置都可以在网站的Web.config中重新配置,且配置方法相同。
⑶单击【创建或管理角色】,由于此时系统中没有任何角色,系统首先提示是否创建一个新角色,在【新角色名称】文本框中输入“网站管理员”,然后单击【添加角色】按钮,即可看到新增的角色。
⑷再添加两个角色,分别为“普通用户”和“禁用账户”,最终结果如图所示。
⑸选择【安全】选项卡,返回该选项卡的主界面,单击【创建访问规则】,左侧的树形目录列出了所有的文件夹,选择某个目录节点后,在右侧设置某种角色、用户的访问权限,权限有【允许】和【拒绝】两种。
⑹选中节点Logins,【角色】设置为【禁用账户】,【权限】设置为【拒绝】,单击【确定】按钮。
⑺返回【安全】选项卡的主界面,单击【管理访问规则】按钮。
⑻返回【安全】选项卡的主界面,单击【管理用户】,系统列出所有用户名,可以通过【搜索用户】选项区查找所有用户。
⑼单击【guest】用户行后面的【编辑角色】,后面显示【角色】选项,只需选中某个角色,即可赋予此账户该角色,此处选中【禁用账户】复选框。另外,如果撤选【活动】下的某个复选框,就可以禁用某个账户。
【运行结果】
按【F5】快捷键运行Login.aspx页面,使用guest登录后,单击【修改密码】,看是否可以打开修改密码窗口,系统会自动跳转至登录窗口,因此有必要在登录窗口上给用户一些提示。
⑴打开Login.aspx窗体,将光标置于Login控件前,按回车键换行。将光标置于第1行,在此处插入一个LoginView控件。
⑵切换到LoggedInTemplate视图,在其中输入“您可能没有权限访问指定页面,可以尝试使用其他账户登录此界面”。
⑶按【F5】快捷键运行该网页,使用admin登录后,单击【修改密码】按钮,查看效果。
18.4 高手点拨
本节视频教学录像:3分钟
<authentication mode="Forms">详细介绍
01 <authentication mode="Forms">
02 <forms loginUrl="Login.aspx"
03 protection="All"
04 timeout="30"
05 name=".ASPXAUTH"
06 path="/"
07 slidingExpiration="true"
08 defaultUrl="default.aspx"
09 cookieless="UseDeviceProfile"/>
10 < /authentication>
11 < /system.web>
loginUrl 指向应用程序的自定义登录页。当ASP.NET判断出该用户请求的资源不允许匿名访问,而该用户未登录时,ASP.NET会自动跳转到LoginUrl所指向的页面,当登录成功后,则跳转回原来请求的页面。
DefaultUrl指向默认页面。
protection 设置为 All,以指定窗体身份验证票的保密性和完整性。
timeout 用于指定窗体身份验证会话的有限生存期。默认值为 30 分钟。
name 和 path 设置为应用程序的配置文件中定义的值。
requireSSL 设置为 false。该配置意味着身份验证 Cookie 可通过未经 SSL 加密的信道进行传输。如果担心会话被窃取,应考虑将 requireSSL 设置为 true。
slidingExpiration 设置为 true 以执行变化的会话生存期。这意味着只要用户在站点上处于活动状态,会话超时就会定期重置。
cookieless 设置为 UseDeviceProfile,以指定应用程序对所有支持 Cookie 的浏览器都使用 Cookie。如果不支持 Cookie 的浏览器访问该站点,窗体身份验证在 URL 上打包身份验证票。
enableCrossAppRedirects 设置为 false,以指明窗体身份验证不支持自动处理在应用程序之间传递的查询字符串上的票证以及作为某个窗体 POST 的一部分传递的票证。
18.5 实战练习
使用Forms身份验证模式新建一个站点,结合登录控件,完成以下工作:
⑴注册几个用户,并分派不同的角色;
⑵在新建页面Users.aspx上用列表显示出所有用户的用户名列表。
共有条评论 网友评论