当服务器接收到对于特定 Web 资源的请求时,ASP.NET 就会使用所请求的 URL 的虚拟目录路径中所有的配置文件来分级计算该资源的配置设置。例如,您有一个网站具有如下的文件结构,其中应用程序的根目录就是应用程序虚拟目录 (Vdir)。
在通常情况下,最后一个配置设置会覆盖父目录中提供的相同节的设置,但节处理程序可能会执行某种不同的继承方案。
例如,作为一名管理员,您可以将应用程序的设置配置为允许所有用户访问应用程序根目录(即映射到应用程序虚拟目录的物理路径)中的 ASP.NET 资源,而只有选定的用户才能访问两个子目录中的 ASP.NET 资源。
假定 SubDir1 目录中有 Web.config 文件而应用程序根目录或 SubDir2 目录中却没有。在这种情况下,ASP.NET 使用两个配置文件。级别最高的文件是位于 systemroot/Microsoft .NET /Framework/versionNumber/CONFIG 目录中的文件。该文件名为 Machine.config,它是计算机级别的文件,所有 ASP.NET 目录和子目录都继承其设置。Machine.config 随 .NET Framework 提供,其中包含了许多默认的 ASP.NET 设置。该文件的安全配置节的默认配置允许所有用户访问全部 URL 资源。在示例的应用程序根目录中没有对安全性进行修改的配置文件,因此所有用户都有权访问其中 ASP.NET 资源(因为该目录继承了计算机级别的配置文件的设置)。如果 SubDir1 目录中的 Web.config 文件包含了仅允许部分用户访问的安全配置节,那么 SubDir2 会继承该设置。因此,所有的用户都有权访问应用程序根目录中的 ASP.NET 资源,但是只有部分用户可以访问 SubDir1 和 SubDir2 中的 ASP.NET 资源。
虚拟目录的配置设置是与物理目录结构无关,虚拟目录必须细心组织,以避免产生配置问题。例如,可能有一个名为 MyResource.aspx 的应用程序具有如下物理目录结构。
C:/Subdir1/Subdir2/MyResource.aspx
假定配置文件位于 Subdir1 中,名称为 Vdir1 的虚拟目录映射到 c:/Subdir1 上,名称为 Vdir2 的虚拟目录映射到 c:/Subdir1/Subdir2 上。如果客户端使用 URL http://localhost/vdir1/subdir2/MyResource.aspx 访问物理路径为 c:/Subdir1/Subdir2/MyResource.aspx 的资源,则该资源从 Vdir1 继承配置设置。然而,如果客户端使用 URL http://localhost/vdir2/MyResource.aspx 来访问相同的资源,则该资源不会从 Vdir1 继承设置。因此,按照这样的方式创建虚拟目录会产生预料不到的结果,甚至使应用程序不能运行。我们并不建议您这样做。
注意 ASP.NET 配置系统仅适用于 ASP.NET 资源(通过 Aspnet_isapi.dll 注册以便由 ASP.NET 处理的资源)。在默认情况下,配置系统不提供对于非 ASP.NET 资源的授权。例如,所有的用户都可以访问 ASP、HTML、TXT、GIF 和 JPEG 文件。在前面的示例中,如果启用了目录浏览且没有其他限制,则所有用户都可以查看应用程序根目录、SubDir1 和 SubDir2 中的非 ASP.NET 文件。有关 ASP.NET 安全的详细信息,请参阅 ASP.NET 安全。
配置
通过使用具有适当 path 属性的
例如,下列配置文件在三个级别上指定了设置:
应用于当前目录和所有子目录的设置,即包含在顶级
应用于 Sub1 子目录的设置,即包含在路径属性设置为 Sub1 的
应用于 Sub2 子目录的设置,即包含在路径属性设置为 Sub2 的
锁定配置设置
默认情况下,位于子目录的配置文件覆盖并扩展父配置文件中定义的所有配置设置。在应用程序宿主方案中,管理员通常要锁定或禁止他人访问站点上的某些设置以免这些设置被修改。例如,管理员可能要锁定宿主应用程序的沙盒安全设置,以防止 Web 用户攻击该系统。
管理员可通过将 allowOverride="false" 属性添加到
以下配置文件示例(可在主系统级别或站点级别存储该文件)锁定两个不同的 ASP.NET 应用程序(application1 和 application2)的信任级别。
如果使用以下示例中的配置设置覆盖上一示例中的配置设置,就会生成一个配置系统错误。
对于 Web 开发人员来说,防止对网站进行未经授权的访问是一个关键而复杂的问题。要获得良好的系统,必须仔细地进行规划,并且网站管理员和程序员必须清楚地知道保护站点安全的各种方法。
ASP.NET 与 Microsoft .NET Framework 以及 Internet 信息服务 (IIS) 一起为 Web 应用程序提供了安全保障。要保护 ASP.NET 应用程序的安全,您必须执行下表中描述的两个基本功能。
安全功能 描述
身份验证 确保用户确实与声明相符。应用程序从用户那里获得凭据(各种格式的标识,如名称和密码),并通过某些机构验证这些凭据。如果凭据有效,则提交该凭据的实体被视为是经过验证的身份标识。
授权 通过允许或拒绝经过验证的标识的特定权限来限制访问权限。
IIS 也能根据用户的主机名称或 IP 地址来允许或拒绝访问。任何进一步访问授权都将由 NTFS 文件访问权限的 URL 授权来执行。
了解所有不同的安全系统如何相互作用很有帮助。因为 ASP.NET 是基于 Microsoft .NET Framework 构建的,所以 ASP.NET 应用程序开发人员可以访问全部 .NET Framework 内置的安全功能,如代码访问安全或基于角色的用户访问安全。有关 ASP.NET 的安全功能的详细信息,请参阅 ASP.NET 代码访问安全。
ASP.NET 结构
本节提供有关 ASP.NET 体系结构与子系统之间关系的概述,因为这些与安全主题相关。下面的插图表示了 ASP.NET 中安全系统之间的关系。
如图所示,所有 Web 客户端都通过 Internet 信息服务 (IIS) 与 ASP.NET 应用程序通讯。IIS 解释请求并且有选择地对请求进行身份验证。如果“允许匿名”设置为 true,则不会进行身份验证。IIS 也会查找所请求的资源(例如,ASP.NET 应用程序),如果客户端得到了授权,则会返回适当的资源。
除了内置的 ASP.NET 功能外,ASP.NET 应用程序还可以使用 .NET Framework 的低级别安全功能。详细信息,请参阅 .NET Framework 帮助中的“密钥安全概念”主题。
与 IIS 集成
在考虑 ASP.NET 身份验证时,应该理解与 IIS 身份验证服务的交互操作。
IIS 总是假定一组凭据映射到 Microsoft Windows NT 帐户并使用其来验证用户。在 IIS 5.0 和 6.0 中有三种不同身份验证方法:基本身份验证、摘要式身份验证、集成 Windows 身份验证(NTLM 或 Kerberos)。在 IIS 管理服务中,您可以选择要使用的身份验证类型。有关 IIS 身份验证的详细信息,请参阅 IIS 帮助。
如果您请求包含 ASP.NET 应用程序的 URL,此请求和身份验证信息就会被传递给该应用程序。ASP.NET 提供下表中所描述的两种其他类型的身份验证。
ASP.NET 身份验证提供程序 描述
Forms 身份验证 通过其可将没有通过身份验证的请求重定向到使用 HTTP 客户端重定向的 HTML 窗体的系统。用户提供凭据并提交该窗体。如果应用程序验证该请求,系统就会在包含凭据或密钥的 Cookie 中发出身份验证票证,以重新获取该标识。后续的请求在请求标题中随 Cookie 一起发出,ASP.NET 处理程序会使用应用程序开发人员指定的任何验证方法去验证请求并给其授权。
Passport 身份验证 由 Microsoft 提供的集中身份验证服务,用于为成员站点提供单一登录和核心配置服务。
使用 ASP.NET 配置文件
ASP.NET 配置(包括安全性)采用分级结构。所有用于 ASP.NET 的配置信息都包含在名称为 Web.config 和 Machine.config 的文件中,Web.config 文件可以放在与应用程序文件相同的目录中。Machine.config 文件在根安装目录下的 Config 目录中。子目录会继承目录的设置,除非被子目录中的 Web.config 文件所覆盖。在 Web.config 文件中有很多部分,每部分都对应着一类主要的 ASP.NET 功能。要查看分级配置系统处理安全问题方法的示例,请参阅分层配置结构。
Web.config 文件中的安全部分组织如下:
protection="[All|None|Encryption|Validation]"
path="[path]" timeout="[minutes]"
requireSSL="[true|false]"
slidingExpiration="[true|false]">
password="[user_password]"/>
这些元素的默认设置如下表所示。
默认值 描述
Web.config 文件有三个主要的子部分:身份验证、授权和标识。通常这样设置每个安全元素的值:用应用程序根目录下应用程序配置文件中相似的部分去覆盖计算机级别配置文件中的部分。所有的子目录都会自动继承那些设置。但是,子目录可以拥有其自己的配置文件用于覆盖其他设置。
注意 ASP.NET 配置仅应用于 ASP.NET 资源(那些已注册由 Aspnet_isapi.dll 处理的资源)。但 ASP.NET 不能为非 Aspnet_isapi.dll 资源提供授权,所以在符合 IIS 权限的情况下,所有用户依然可以访问 TXT、HTML、GIF、JPEG、ASP 和其他类型的文件。例如,即使 Web.config 文件可能限制了某个目录中的 ASP.NET 资源,如果打开了目录浏览且没有其他限制,所有用户依然可以查看位于那个目录中的文件。
通过使用 IIS 管理工具明确地将这些文件而不是目录映射到 Aspnet_isapi.dll,可以避免这种情况发生。但是,这样可能会对性能产生影响。
您可以使用
ASP.NET 数据流
在 ASP.NET 应用程序中进行安全设计有许多不同的方法。本节描述用于两种通用方案的数据流:模拟和使用 Cookie 的 Forms 身份验证。
方案 1:模拟
该方案根据 Internet 信息服务 (IIS) 身份验证和 Microsoft Windows NT® 文件访问安全,将对 ASP.NET 应用程序自身的安全性程序设计减少到最少。下面的插图显示了数据流。
插图显示了以下事件顺序:
来自网络客户端的访问请求到达 IIS。
IIS 使用基本身份验证、摘要式身份验证或集成 Windows 身份验证(NTLM 或 Kerberos)对客户端进行验证。
如果客户端通过身份验证,IIS 就会将已验证的请求移交给 ASP.NET。
ASP.NET 应用程序使用由 IIS 传递的访问令牌来模拟正在请求的客户端,并依赖 NTFS 文件权限授权访问要求。ASP.NET 应用程序仅需要验证 ASP.NET 配置文件中的内容,将启用模拟的指令设置为 true,则不需要编写任何 ASP.NET 安全代码。
请注意如果没有启用模拟,应用程序就会以 IIS 进程标识运行。对于 Microsoft Windows® 2000 Server 和 Windows XP,默认的标识是在 ASP.NET 安装时自动创建的、名称为 ASPNET 的用户帐户。对于 Microsoft Windows Server 2003 家族产品,默认标识是 Network Service 帐户。如果要限制访问,必须使用授权的其他方法,例如 URL 授权。
有关在 ASP.NET 应用程序中使用模拟的详细信息,请参阅模拟和通过 ASP.NET 模拟使用 IIS 身份验证。
如果被授予了访问权限,则 ASP.NET 应用程序将通过 IIS 返回所请求的页面。
方案 2:Forms 身份验证
在该方案中,应用程序使用 ASP.NET Forms 身份验证,该过程可使应用程序收集直接来自客户端请求者的凭据(如名称和密码),并对其可靠性做出自己的判断。虽然应用程序并不使用 IIS 身份验证,但 IIS 身份验证设置对于 ASP.NET Forms 验证过程非常重要。除非您决定拒绝所有不符合已启用的 IIS 身份验证方法标准的请求,否则必须启用 IIS“匿名访问”设置。
注意 如果没有启用 IIS“匿名访问”设置,不符合 IIS 身份验证标准的请求将被拒绝而且永远不会到达 ASP.NET 应用程序。
该方案中的数据流如下图所示。
该插图显示了以下的事件顺序:
客户端生成一个对受保护资源的请求。
IIS 接收到该请求,如果该请求者经过 IIS 身份验证,或启用了 IIS“匿名访问”,则请求将传递到 ASP.NET 应用程序。在这种情况下,因为 ASP.NET 应用程序中的身份验证模式设置为 Forms,所以没有使用 IIS 身份验证。
如果没有 Cookie 附加到该请求,ASP.NET 将该请求重定向到登录页面,其页面路径保存在应用程序的配置文件中。在登录页面上,客户端输入必需的凭据(通常是名称和密码)。
应用程序代码检查凭据以确认其可靠性,通常在事件处理程序中。如果凭据通过了身份验证,则应用程序代码将附加上包含用户名称(但没有密码)的票据,例如 Cookie。如果没有通过身份验证,该请求通常返回“访问拒绝”信息或再次显示登录页面。
应用程序发出票据以后,ASP.NET 会使用消息身份验证检查来检查票据的有效性。应用程序不需要 *.config 文件中的凭据。实际上,ASP.NET 在发出 Cookie 后并不检查凭据,即使它们存在。
如果用户通过了身份验证,ASP.NET 会检查授权,然后允许访问最初所请求的、受保护的资源,或将请求重定向到其他页面上,这取决于应用程序的设计。它也可以将请求定向到自定义的授权模块上,在该模块中将检查凭据,以用于对所访问的受保护资源进行授权。如果没有通过授权,ASP.NET 会始终重定向到登录页面。
如果用户已被授权,则允许对受保护资源的访问;或应用程序在对受保护资源授权以前可能要求附加的凭据验证,这取决于应用程序的设计。
ASP.NET 身份验证
身份验证是从用户获取名称和密码等标识凭证并根据某些机构验证这些凭据的过程。如果凭据有效,则提交该凭据的实体被视为通过身份验证的标识。一旦标识通过了身份验证,则身份验证过程会确定该标识是否可以访问给定的资源。
ASP.NET 通过身份验证提供程序、包含验证请求者凭据所需代码的代码模块来实现身份验证。ASP.NET 支持下表所描述的身份验证提供程序。
ASP.NET 身份验证提供程序 描述
Forms 身份验证 通过其可将没有通过身份验证的请求重定向到使用 HTTP 客户端重定向的 HTML 窗体的系统。用户提供凭据并提交该窗体。如果应用程序验证该请求,系统就会发出包含凭据或密钥的 Cookie 以重新获取该标识。后续的请求在请求标题中随 Cookie 一起发出,ASP.NET 事件处理程序会使用应用程序开发人员指定的任何验证方法去验证请求并给其授权。
Passport 身份验证 由 Microsoft 提供的集中身份验证服务,用于为成员站点提供单一登录和核心配置服务。
Windows 身份验证 ASP.NET 会结合 Internet 信息服务 (IIS) 身份验证使用 Windows 身份验证。IIS 以下列三种方式执行身份验证:基本身份验证、摘要式身份验证或集成 Windows 身份验证。当 IIS 身份验证完成后,ASP.NET 会使用验证过的标识授权访问权限。
要为 ASP.NET 应用程序启用身份验证提供程序,仅需按照以下方法为应用程序配置文件创建一个条目。
// Web.config file
模式可设置为下列身份验证模式之一:Windows、Forms、Passport 或 None。默认为 Windows。如果将模式设置为 None,ASP.NET 不会对该请求应用任何附加身份验证 - 当要实现自定义的身份验证方案,或只想使用匿名身份验证并想获得尽可能高的性能级别时,这是很有用的。
身份验证模式不能在应用程序根目录以下的级别进行设置。其他 ASP.NET 模块也是如此,在 URL 中的子目录会继承身份验证模块,除非其被明确覆盖。
WindowsAuthenticationModule 提供程序使用 IIS 所支持的任何一种机制,依赖 Internet 信息服务 (IIS) 提供已通过身份验证的用户。如果想要以最少的 ASP.NET 代码来保护站点安全,那么这就是应该使用的提供程序配置。提供程序模块构建了 WindowsIdentity 对象。其默认实现构建了 WindowsPrincipal 对象并将其附加在应用程序的上下文中。WindowsPrincipal 对象将标识映射到 Windows 组中。
如果使用 IIS 身份验证,则提供程序模块将使用从 IIS 传递进来的已通过身份验证的标识。IIS 通过使用基本身份验证、摘要式身份验证、集成 Windows 身份验证或它们的组合来验证标识。可以使用模拟和 NTFS ACL 权限限制或允许对受保护资源的访问。
使用 WindowsAuthenticationModule 提供程序的一个重要原因是要实现一种模拟方案,该方案在将请求传递给 ASP.NET 应用程序前,能够使用可能已被 IIS 执行的任何验证方法。为此,请将身份验证模式设置为 Windows,并确认将 impersonate 元素设置为 true,如下例所示:
请注意配置 ASP.NET 应用程序不会影响 IIS 目录安全设置。系统之间完全独立并按顺序应用。除了选择 ASP.NET 应用程序的身份验证模式,正确地配置 IIS 身份验证也很重要。
接下来,必须设置 NTFS ACL 只允许适当的标识进行访问。
Passport 身份验证提供程序
Passport 身份验证是指由 Microsoft 提供的集中身份验证服务,用于为成员站点提供单一登录和核心的配置文件服务。它给用户带来了很大的方便,因为不再需要登录以访问新的加密资源或站点。若要使您的站点与 Passport 身份验证和授权兼容,则应该使用该提供程序。此主题提供了一些有关 Microsoft 的介绍性材料。NET Passport 及其 ASP.NET 支持。有关的详细信息,请参阅位于 http://www.passport.com/business 的 Passport 文档。要访问该文档,您必须获取一个 Passport 并注册。
Passport 是基于 Cookie 的身份验证服务。使用 Passport 身份验证的示例事务转换与以下内容类似:
客户端针对受保护的资源发出 HTTP GET 请求,如 http://www.contoso.com/default.aspx。
检查客户端的 Cookie 是否有现有 Passport 身份验证票据。如果站点找到了有效的凭据,则站点对客户端进行身份验证。如果请求不包含有效的身份验证票据,则服务器返回状态代码 302 并将客户端重定向到 Passport 登录服务。响应包括查询字符串中的 URL(被发送到 Passport 登录服务以将客户端定向回初始的站点)。
客户端执行重定向并再次请求初始的资源,此次使用的是 Passport Cookie。
Passport 登录服务器给客户端显示登录表单。
客户端填充表单,并使用安全套接字层 (SSL) POST 返回到登录服务器。
登录服务器对用户进行身份验证并将客户端重定向到初始的 URL (http://www.contoso.com/default.aspx)。响应在查询字符串中包含加密的 Passport Cookie。
客户端执行重定向并再次请求初始的受保护资源,此次使用的是 Passport Cookie。
还是在初始服务器上,PassportAuthenticationModule 检测 Passport Cookie 是否存在并对它进行测试以进行身份验证。如果成功,则对请求进行身份验证。
对于在站点发出的对受保护资源的后续请求,在初始服务器上使用提供的票据对它们进行身份验证。Passport 还对票据到期和在其他成员站点上重用票据提供支持。
Passport 使用三重 DES 加密方案。当成员站点使用 Passport 进行注册时,就会给它们授予站点特定的密钥。Passport 登录服务器使用此密钥加密和解密在站点之间传递的查询字符串。
注意 要使用 Passport 身份验证,此前必须使用 Passport 服务注册您的站点,接受许可协议以及安装 .NET Passport SDK。
ASP.NET PassportAuthenticationModule 为 ASP.NET 应用程序提供了 .NET Passport SDK 包装,并从 IIdentity 派生类 PassportIdentity 提供了 Passport 身份验证服务和配置文件信息。
与 WindowsIdentity 相同,处理 PassportAuthentication_OnAuthenticate 事件的主要目的是将自定义 IPrincipal 对象与上下文关联起来。特殊的 IIdentity 派生类 PassportIdentity 给 Passport 配置文件信息提供了一个接口,并提供了加密和解密 Passport 身份验证票据的方法。
在 ASP.NET 应用程序中执行 Passport 身份验证
从 http://www.passport.com/business 下载、安装和配置 .NET Passport SDK。必须填写注册表单以获取 SDK。Windows Server 2003 包含 .NET Passport SDK,不需要此步骤。
在应用程序配置文件中按如下方式将 Passport 设置为身份验证模式。
通过使用 Passport 文档和 .NET Passport SDK 功能来执行 Passport 身份验证和授权。
有关使用 Passport 身份验证的 ASP.NET 页代码示例,请参阅 MSDN Library 中的文章“Creating a Microsoft .NET Passport-Authenticated Web Site with ASP.NET”。
Forms 身份验证提供程序
Forms 身份验证通常是指以下系统:使用 HTTP 客户端重定向功能将未经验证的请求重定向到某个 HTML 表单。如果应用程序在通过 HTML 表单登录时需要搜集其自己的用户凭据,则 Forms 身份验证是一种很好的选择。用户提供凭据并提交该窗体。如果应用程序验证该请求,则系统发出一个包含凭据或密钥的 Cookie 以重新获取标识。随后的请求是使用请求标题中的 Cookie 来发布的。请求是由 ASP.NET 事件处理程序使用应用程序指定的验证方法来验证和授权的。
注意,Forms 身份验证通常用于自定义,即为已知用户自定义内容。在某些情况下,需要进行标识而无需进行身份验证,因此,只需要在持久的 Cookie 中存储用户名并使用该 Cookie 访问该用户的自定义信息就可以了。
有关如何开发使用 Forms 身份验证的 ASP.NET 应用程序的详细信息,请参阅 MSDN Library 中有关 Forms 身份验证提供程序的文档。
跨应用程序 Forms 身份验证
ASP.NET 在分布式环境中支持 Forms 身份验证,即跨单个服务器或 Web 场上的应用程序。对于参与共享 Forms 身份验证的所有应用程序,
protection="all"
timeout="30"
path="/" >
validationKey= "C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA1742572A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE"
decryptionKey= "8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F"
validation="SHA1"
isolateApplications="false"
用于 Cookie 数据的加密、验证密钥和加密方案必须完全相同。如果设置不匹配,则无法共享 Cookie。
系统发出一个 Cookie 后,会基于 Cookie 本身中的 Expires 属性值来跟踪 Cookie 是否到期。这意味着,如果两个应用程序具有不同的 timeout 属性,则在每个 Cookie 的生存期内,保留 Cookie 最初颁发时设置的到期日期和时间。在更新 Cookie 后,可使用该 Cookie 的原始到期时间来计算新的到期时间。仅在初始创建 Cookie 时,使用配置 timeout 值。
ASP.NET 授权
授权的目的是确定是否为标识授予对给定资源访问的请求类型。有两种对给定资源进行授权访问的基本方法:
文件授权
文件授权由 FileAuthorizationModule 执行,且当使用 Windows 身份验证时,文件授权处于活动状态。它对 .aspx 或 .asmx 处理程序文件进行访问控制列表 (ACL) 的检查,以确定用户是否应具有访问权。应用程序可以进一步使用模拟方法对所访问的资源进行资源检查。有关模拟的详细信息,请参阅 ASP.NET 模拟。
URL 授权
URL 授权由 URLAuthorizationModule 类执行,该类会将用户和角色映射到 URL 名称空间的各个部分中。该模块可以实现肯定和否定的授权断言。也就是说,可以使用该模块选择性地允许或拒绝特定的集合、用户以及角色对 URL 名称空间中任意部分的访问。
URLAuthorizationModule 在任何时候都是可用的。仅需将用户和/或角色列表放在某个配置文件的
要建立访问某一特定目录的条件,必须将含有
<[element] [users] [roles] [verbs]/>
element 是必需的。必须包含 users 或 roles 属性。也可同时包含两个,但包含两个并不是必需的。verbs 属性是可选的。
允许的元素是
属性 描述
roles 为该元素识别目标角色。该请求的相关 IPrincipal 对象确定角色的成员身份。可以将任意 IPrincipal 对象附加到给定请求的上下文中,然后这些对象可以用您选择的任何方法来确定角色成员身份。例如,默认的 WindowsPrincipal 类使用 Microsoft Windows NT 组来确定角色成员身份。
users 为该元素识别目标标识。
verbs 定义操作所应用的 HTTP 动作,例如,GET、HEAD 和 POST。
也拒绝匿名用户。
下例将访问权限授予 Kim 和 Admins 角色的成员,同时拒绝 John 和所有匿名用户的访问:
用户和角色都可以使用由逗号分隔的列表引用多个实体,如下例所示。
请注意域账号 (contoso/Jane) 必需包含域名和用户名的组合。
除了标识名称外,还有两种特殊标识,如下表所示。
标识 描述
* 引用所有标识
? 引用匿名标识
要允许 John 而拒绝任何其他用户的访问,可能要构建如下的配置部分。
下例使每个人都可以执行 GET 动作,但只有 Kim 才能使用 POST。
使用下面的启发式方法来应用规则:
位于较低目录级别中的配置文件所包含的规则优先于位于较高目录级别中的规则。系统通过构建 URL 的所有规则合并列表,结合离列表起始处最近的规则(在分级结构中最靠近的)来确定优先的规则。
如果给定了针对 URL 的一组合并规则,系统将从列表起始处开始检查规则,直到发现第一个匹配为止。请注意 ASP.NET 的默认配置包含授权所有用户的
如果
还可以使用
ASP.NET 模拟
使用模拟时,ASP.NET 应用程序可以选择在它们所代表的客户端标识下执行操作。这样做的原因是可以避免在 ASP.NET 应用程序代码中处理身份验证和授权问题。相应的,根据 Internet 信息服务 (IIS) 对用户进行身份验证,然后或者将已通过身份验证的令牌传递到 ASP.NET 应用程序,或者在无法对用户进行身份验证时,传递未经验证的令牌。在上述任何一种情况下,如果启用了模拟,则 ASP.NET 应用程序会模拟所收到的任何令牌。然后,模拟客户端的 ASP.NET 应用程序根据 NTFS 目录和文件的设置使自己获得访问权限或者得不到访问权限。确保将服务器的文件空间格式化为 NTFS 格式,以便设置访问权限。
在默认情况下禁用模拟。考虑到 ASP 的兼容性,用户必须明确地启用模拟。如果为某一给定的应用程序启用了模拟,ASP.NET 总是模拟 IIS 提供给 ISAPI 扩展的访问令牌。该令牌或者是已通过身份验证的用户令牌,或者是匿名用户的令牌(如 IUSR_MACHINENAME)。模拟的发生与应用程序中正在使用的身份验证类型无关。
只有应用程序代码才能被模拟;编译和配置作为进程令牌进行读取。编译的结果放在“Temporary ASP.NET files”目录中。正被模拟的帐户需要有该目录的读/写访问权限。如果应用程序位于通用命名约定 (UNC) 的共享上,ASP.NET 将总是模拟提供给 IIS 的令牌来访问该共享,除非使用了已配置的帐户。如果提供了明确配置的帐户,ASP.NET 将使用该帐户而不使用 IIS UNC 令牌。不希望进行每个请求模拟的应用程序可简单地配置为模拟发出请求的用户。
在默认情况下,在计算机级别禁用模拟,所有的应用程序域会继承该设置(除非该设置被覆盖)。通过将配置文件放置在应用程序根目录下可以启用模拟。有关 ASP.NET 配置系统的详细信息,请参阅 ASP.NET 配置。
和其他配置的指令一样,该指令也是按层次结构进行应用。在层次结构中嵌套的应用程序遵守该指令,除非它被明确地覆盖。下面是此设置的默认值。
启用应用程序模拟的最小配置文件与下面的示例类似。
将应用程序作为可配置标识运行也要有名称支持。例如:
这使得整个应用程序作为 contoso/Jane 运行,只要密码正确而与请求的标识无关。这种类型的模拟能够被委派给另一台计算机。
可以通过编程来读取被模拟用户的标识,如下例所示。
[Visual Basic]
Dim username As String = System.Security.Principal.WindowsIdentity.GetCurrent().Name
[C#]
String username = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
在前面的示例中,userName 和 password 以明文形式存储在配置文件中。尽管 IIS 将不会为响应用户代理请求而传输 .config 文件,但是可通过其他方法读取配置文件,例如,通过对包含该服务器的域具有正确凭据的经过身份验证的用户访问。为了维护安全性,标识部分支持在注册表中存储加密的 userName 和 password 属性,如下例所示。
userName="registry:HKLM/Software/AspNetIdentity,Name"
password="registry:HKLM/Software/AspNetIdentity,Password"
关键字 registry 后面、第一个逗号前面的字符串部分表示 ASP.NET 必须要打开的注册表项。逗号后面的部分包含一个字符串值名,ASP.NET 将从中读取凭据。逗号是必需的,凭据必须存储在 HKLM 配置单元中。如果配置格式有误,则 ASP.NET 将不启动工作进程,并随后出现当前帐户创建失败代码的路径。
关键字 registry 后面、逗号前面的字符串部分表示 ASP.NET 所打开的注册表项的名称。逗号后面的部分包含一个字符串值名,ASP.NET 将从中读取凭据。逗号是必需的,凭据必须存储在 HKLM 配置单元中。如果配置格式有误,则 ASP.NET 将不启动工作进程,并随后出现当前帐户创建失败代码的路径。
凭据必须采用 REG_BINARY 格式,其中包含对 Windows API 函数 CryptProtectData 调用的输出结果。您可以用 ASP.NET 设置注册表控制台应用程序 (Aspnet_setreg.exe) 创建加密凭据并将其存储在注册表中,该应用程序使用 CryptProtectData 完成加密。要下载 Aspnet_setreg.exe 以及 Visual C++ 源代码和帮助,请访问网站 www.asp.net 并搜索 aspnet_setreg。
您应该对存储加密凭据的注册表项配置访问权限,以便只对 Administrators 和 SYSTEM 提供访问。因为该注册表项将由作为 SYSTEM 运行的 ASP.NET 进程读取,您应该设置下列权限:
Administrators:F
SYSTEM:F
CREATOR OWNER:F
ProcessAccount:R
这将提供两道防线来保护数据。
ACL 权限要求访问数据的标识为 Administrator。攻击者必须在服务器上运行代码 (CryptUnprotectData) 以便恢复帐户的凭据。
本节中的示例说明了如何创建集成了各种行业标准安全技术的 ASP.NET 应用程序。有关如何创建使用 Forms 身份验证的示例,请参阅 MSDN Library 中的 Forms 身份验证信息。
同时使用 IIS 身份验证和 ASP.NET 模拟
在此方案中,您将设置 Intranet 网站中的应用程序,以发布雇员信息。但有些信息是管理者专用的。管理者的信息可发布到一般员工信息的子目录中,这样就可以限制对它的访问。该方案还假定:
您使用的是 Microsoft Windows NT 或 Microsoft Windows 2000 server。
硬盘的格式为 NTFS。
Web 服务器是 Internet 信息服务 (IIS) 6.0。
所有要访问的雇员都使用 Windows 平台。
作为管理员的您:
可创建下图所示的文件和目录。
创建一个称作“Managers”的 Windows 组,其中包含了所有有权访问 ManagerInfo.aspx 文件的用户。
使用 IIS 管理工具设置 Windows 身份验证。
将 ASP.NET 配置文件的
将 ManagerInformation 目录的 NTFS 访问控制列表 (ACL) 设置为仅允许 Windows 管理者组中的那些标识访问。请注意,仍需要访问本地系统,这样 ASP.NET 进程本身就可以读取这些文件了。目录中的设置通常类似于以下情况:
如果 Everyone 组有访问权限,请从该组中将其清除。
拒绝匿名用户。
添加具有访问特权的帐户。
授予系统帐号访问权限。
这提供了必要的安全保障,并且无需编写任何代码。
配置 ASP.NET 进程标识
ASP.NET 工作进程 (Aspnet_wp.exe) 应使用不同于 Windows 默认的“系统”身份的享有较少特权的身份运行。这允许进程作为一个相对不受信任的用户来运行,以便使由其主控的 Web 应用程序没有管理特权,且不会损坏服务器的完整性。如果 ASP.NET 工作进程的安全遭到破坏,只会危及相对较弱帐户的安全,入侵者不会拥有对整个服务器的管理访问权限。
要在 Windows 2000 和 Windows Server 中使用 ASP.NET 工作进程自身的帐户运行它,您可将下面的两个属性应用到
userName
运行进程时使用的帐户名。
password
帐户的明文密码。将明文密码保存在配置文件中会有风险。对于发布到 Internet 上的应用程序,您应该使用其他方法以特定身份运行应用程序,或者将加密凭据存储在注册表中。有关在注册表中存储凭据的详细信息,请参阅
如下示例显示了如何在配置文件的
password="password"/>
“系统”和“计算机”是两个预定义的 userName 身份设置。“系统”帐户使用与 Internet 信息服务 (IIS) 本身相同的身份(通常是“系统”)运行工作进程。“计算机”帐户使用的一个特殊的无特权帐户(称为 ASPNET)运行工作进程。两个身份的密码都是 AutoGenerate,这表示进程无需向操作系统提供凭据。
要允许使用特殊的 ASPNET 帐户运行进程,请在 Machine.config 文件中添加下列行。若要更改 Machine.config 中的进程帐户,必须重置 IIS 或停止 Aspnet_wp.exe 进程。
password="AutoGenerate"/>
对于 Internet 信息服务第 6 版中启用的新进程模型,ASP.NET 将不使用自身的进程模型。其身份是从 IIS 工作进程中继承来的。
仅当您将相应的帐户权利显式添加到运行工作进程时使用的帐户中时,才能支持下面的示例。将明文密码保存在配置文件中会有风险。对于发布到 Internet 上的应用程序,您应该使用其他方法以特定身份运行应用程序,或者将加密凭据存储在注册表中。有关详细信息,请参阅
password="password"/>
下列各段介绍的技巧是 ASP 站点的管理员经常使用的技巧,并且在进程身份较弱的 ASP.NET 环境中起作用。
应用程序允许匿名用户进行访问(假定身份验证方案允许匿名用户访问),且匿名用户也配置为应用程序所需的帐户。同时,应用程序还使用基于请求的模拟,并且应用程序代码作为模拟帐户来执行。因为模拟只用于请求处理程序,所以进程帐户仍读取和编译配置。
如果您在使用具有管理员特权的帐户运行工作进程和使用较弱的帐户运行工作进程之间来回替换,则较弱的帐户不能读取用于 Forms 身份验证的本地安全机构 (LSA) 机密,因此所有 Forms 身份验证用户都必须重新进行身份验证。从没有管理特权的帐户到有管理特权的帐户转换时,并不适用。它适用于具有下列配置的应用程序。
ASP.NET 必需的访问控制列表 (ACL)
下表显示了 ASP.NET 为访问所列出的位置,必须具有的访问权限类型。
位置 访问类型 帐户 注释
installroot/ASP.NET 临时文件 读取/写入 进程或配置的模拟。 这是动态编译的文件的位置。在该位置下,应用程序代码生成就发生在每个应用程序的离散目录中。使用
systemroot/assembly 读取 进程或配置的模拟。 这是全局程序集缓存的位置。
systemroot/system32 读取 进程 包含 .NET Framework 加载的系统 DLL。
systemroot/temp 读取/写入/删除 进程 用于 XML Web 服务支持。
userprofile 目录 读取/写入 进程 由全局程序集缓存锁定文件和公共语言运行库安全配置缓存机制使用。如果帐户的用户配置文件目录不存在,ASP.NET 将使用默认的 userprofile 目录。
application 目录 读取 进程或配置的模拟。 这是应用程序文件的位置。
installroot 层次结构 读取 进程或配置的模拟 ASP.NET 必须能够访问 installroot 下 config 子目录的 Machine.config 文件中所引用的系统程序集。
默认网站监视 读取 进程 用于文件变化的通知监视。
ASP.NET 代码访问安全
使用 ASP.NET 主控多个站点的一个主要好处是公共语言运行库对于代码访问安全的支持,这样可以为服务器应用程序提供执行平台。系统根据代码的来源证据(例如,具有强名称的程序集或者来源的 URL)将其指派到安全区域分类。如果不能对安装在公用服务器上的单个、不相关的应用程序进行安全配置,那么属于某个应用程序的 ASP.NET 页中的代码就可以读取另一个应用程序中的文件(如 Web.config 文件)了。以完全信任方式运行的应用程序仅受其执行时使用的操作系统帐户的约束。
通过强命名操作和向程序集添加策略,可以轻松处理单个程序集的代码访问安全问题。然而,很多 ASP.NET 程序集都是动态页编译过程动态产生的结果,因而没有强名称,所以需要使用其他的程序。
ASP.NET 允许您将对应于预定义权限集的可配置信任级别指派给应用程序。在默认情况下(除非明确地更改配置),应用程序会收到与其提供的证据相当的信任级别。例如,本地应用程序必须在 MyComputer 区域中使用 Full 信任权限集运行,而通用命名约定 (UNC) 共享上的应用程序则必须在 Intranet 区域中使用 LocalIntranet 受限权限集运行。如果想运行信任级别比 Full 低的 Web 应用程序,您必须使用在 ASP.NET 信任级别和策略文件中预定义的某项信任级别来执行部分信任策略。
可以使用下列配置设置替代默认行为,并使应用程序与给定的安全策略相关联。
如果要为整个站点设置策略,您可以通过将站点的根指定为路径位置来实现,方法如下。
如果不想让程序有能力指定自身的信任级别(在大多数共享服务器安装上的情况),应注意使用 allowOverride 属性来指定
下表列出了
属性 描述 默认支持的值
level 指定应用程序将在其中运行的安全区域。 Full、High、Medium、Low 和 Minimal。
originUrl 允许管理员设置应用程序的原始 URL。
这将允许依赖主机概念的权限正常发挥作用。
标准格式的 HTTP URL。
在默认情况下,与各种安全级别相关的策略享有下表所示的权限。
级别
权限 Full High Medium Low Minimal
AspNetHostingPermission Full High Medium Low Minimal
环境 未 未 读取:TEMP、TMP、OS、USERNAME、COMPUTERNAME
FileIO 未 未 读取、写入、追加和查找路径:应用程序目录 读取、查找路径:应用程序目录
IsolatedStorage 未 未 AssemblyIsolationByUser, 未限制的 UserQuota 1 兆配额(可以为单个站点改变),AssemblyIsolationByUser
反射 未 ReflectionEmit
注册表 未
安全 未 执行、断言、ControlPrincipal、ControlThread、RemotingConfiguration 执行、断言、ControlPrincipal、ControlThread、RemotingConfiguration 执行 执行
套接字 未 未
WebPermission 未 未 连接到原始主机(如果已配置)。
DNS 未 未 未
打印 未 默认打印 默认打印
OleDBPermission 未
SqlClientPermission 未 未 AllowBlankPassword=false
EventLog 未
消息
队列 未
服务
控制器 未
性能
计数器 未
目录
服务 未
未 = 未限制的
空白 = 无权限
当某个权限级别可用但并未在安全策略中明确提出时,以 Full 信任级别运行的应用程序将可以使用该级别(因为它们设置了 Full 信任权限集)。以较低的信任级别运行的应用程序不能使用受非显式许可保护的资源,除非您专门更改策略来允许这样做。
如该表所示,High 信任级别的应用程序拥有对应用程序目录中的文件的读取/写入权限,而 Low 信任级别的应用程序仅对应用程序目录中的文件有只读权限。因为 FileIO 权限依赖于物理路径(如 c:/MyAppPath),所以 ASP.NET 在策略文件中使用标记化的语句,该语句在运行时会由相关的路径信息替代。
请注意,WebPermission 允许应用程序连接到原始主机。通过在
SocketPermission 接受主机名或用点分隔的 IP 字符串(也许带有通配符),而 WebPermission 则接受包含协议的正则表达式(如 http://backendmachine/.*)。如果要对此进行更改,您可以更改策略文件以使用所需的权限(或者通过复制默认值创建新的策略文件)。例如,您可以从 ASP.NET 命名权限集中变更 SocketPermission 节,以便允许在 8080 端口上通过 TCP 套接字连接到“backend1”和“backend2”,方法如下。
ASP.NET 信任级别和策略文件
信任级别与使用
如果不希望让应用程序指定其自身的信任级别(大多数共享服务器方案中的情况),您应注意使用属性 allowOverride=False 指定
Full 信任级别是一种特殊情况。因为它完全等同于在本地计算机区域拥有的全部信任,所以 ASP.NET 主机不会将任何其他的策略应用到这些应用程序中。因此,它被映射到内部处理程序,且主机不会向 Full 信任应用程序的应用程序域添加其他策略。
为了保留默认设置,ASP.NET 将附带每个默认文件的两份副本。一份副本就如上面在配置节中描述的那样,第二份拷贝将具有 .default.config 扩展名,而且系统不会直接使用它。
ASP.NET 策略机制
各种不同信任级别的应用程序域策略由策略级别组成,例如,作为应用程序域策略载入并应用到应用程序域的 System.Security.Policy.PolicyLevel 类的实例。策略树本身与 High、Medium、Low 和 Minimal 信任级别是相同的(不会向 Full 应用任何策略),但 ASP.NET 权限集中的许可权限集除外。下表显示了具有 High 信任级别权限的策略树。
如果要找到全局程序集缓存的位置,请在注册表项 HKLM/Software/Microsoft/Fusion 中检查“CacheLocation”。如果此项不存在,则将默认位置为 %windir%/assembly。
使用 UrlMembershipCondition 对象的三个代码组依赖于在运行时动态计算的路径;ASP.NET 将载入策略文件并替换进行专门分隔的参数(例如,它在执行策略解析前用适当路径替换 $AppDirUrl$)。
在计算给定应用程序的应用程序域策略后(在该步骤中不必执行 Full 信任应用程序),该策略会被应用到应用程序域。应用程序域策略与各种其他不同的策略级别(企业级、计算机级和用户级)交叉在一起,所以它只能进一步限制但不能扩展现有策略。
要查看如何将应用程序域策略用于限制授予的权限,请考虑下表中显示的虚构权限集。
级别 名称 权限
企业 P1 {A, B, C, D}
计算机 P2 {A, B, C}
用户 P3 {A, B, C}
应用程序域 P4 {A, B}
这些策略集的简化应用程序权限(忽略权限请求)可能会是在不同级别所授予的权限的交集。因此,P1、P2、P3 和 P4 的交集是 {A, B}。
管理策略文件
策略文件可以进行手动编辑。您可以使用“.NET Framework 配置工具”或“代码访问策略工具”管理企业级、计算机级和用户级的安全策略。有关使用这些工具的详细信息,请参考 .NET Framework 帮助中的“管理安全策略”主题。
所有的 ASP.NET 应用程序都使用 IIS 虚拟目录作为其应用程序根目录。本主题中的过程显示了如何在 IIS 中创建虚拟目录。
准备该过程
创建新目录。本次演练使用目录 C:/myWebApp。
接下来,打开 IIS 管理器,然后使用下面的过程创建虚拟目录。
在运行 Windows Server 2003 的计算机上创建虚拟目录
从“开始”菜单,指向“管理工具”,然后单击“Internet 信息服务 (IIS) 管理器”。
展开“本地计算机”,然后再展开“网站”。
右键单击“默认网站”,指向“新建”,然后单击“虚拟目录”。
在虚拟目录创建向导中,单击“下一步”。
在“别名”框中键入应用程序名称,然后单击“下一步”。
键入为准备这次演练而创建的物理目录路径 C:/myWebApp,然后单击“下一步”。
在“访问权限”页面中,选择您需要的应用程序的访问权限,然后单击“下一步”。
单击“完成”。
为 ASP.NET 应用程序创建目录结构
如何组织应用程序中包含的目录会影响到应用程序中的文件所包括的任何虚拟或相对路径。另外,如果应用程序使用本地编译代码,必须将 /Bin 目录直接包含在应用程序的根下。ASP.NET 将自动解析对存储在这里的组件的所有引用。
本主题中的过程解释了哪个目录会包含在 ASP.NET Web 应用程序的根目录中。接着对可能的目录结构稍加讨论,在本主题的末尾包含了带有可能的文件名的示例目录。
准备这次演练
如用 IIS 创建 ASP.NET 应用程序根目录所述,为应用程序创建根目录并将其标记为应用程序。
为 ASP.NET Web 应用程序创建目录结构
在命令提示符下或在 Windows 资源管理器中,打开创建的根目录。
创建一个新目录并将其命名为 Bin。
创建应用程序需要的所有其他目录。例如,可以创建一个目录以放置应用程序所包含的所有图像。
/Bin 目录是 Web 应用程序的默认程序集缓存。除非 Web 应用程序与另一个应用程序共享 DLL,否则会将应用程序使用的所有的 DLL 放在 /Bin 目录中,以确保包含在它们中的对象引用能够被正确解析。这些程序集中可以包含商业规则或已编译的自定义服务器控件。如果应用程序与其他应用程序共享程序集,可将共享的 DLL 放在全局程序集缓存中。详细信息,请参阅将共享组件部署到全局程序集缓存。
注意 当在 Visual Studio .NET 环境中创建 ASP.NET Web 应用程序时,这些指令并不应用于由 Visual Studio .NET 编译的程序集。有关使用 Visual Studio .NET 部署开发的 Web 应用程序的信息,请参阅 Visual Studio 帮助。
如果要修改 Web 应用程序的默认配置,请创建 Web.config 文件,进行所期望的修改,然后将其保存在根目录中。详细信息,请参阅 ASP.NET 配置。
另外,如果要编写所有应用程序范围内的函数(其中包括用于 Application_Error 事件的处理程序),请将其放在 Global.asax 文件中并把该文件保存在应用程序根目录中。详细信息,请参阅 .NET Framework 帮助中的“ASP.NET 应用程序”主题。
在下例的目录结构中,C:/myWebApp 是应用程序的根目录。要使应用程序工作正常,myWebApp 目录必须是 IIS 虚拟目录。
注意 此示例应用程序包括了 /Bin 目录和存储与应用程序相关的图像的 |Img 目录。实际的目录结构可能比这个更复杂一些。
c:/myWebApp
Default.aspx
Menu.ascx
Service.asmx
Web.config
Global.asax
/Bin
myBizLogic.dll
/Img
myImage.gif
部署本地应用程序组件
ASP.NET 应用程序组件是应用程序用于执行各种任务的所有 DLL 文件。这些组件可以包括三层应用程序的商业规则和数据库访问规则,也可以包含已开发的自定义 ASP.NET 服务器控件。要用于应用程序,与这些组件相关的每个 DLL 都必须部署到应用程序的 /Bin 目录中。
从命令行中部署 ASP.NET 应用程序组件
从“开始”菜单,单击“运行”。
在“运行”对话框中的“打开”框中,键入 cmd,然后单击“确定”。
在命令提示符下,键入以下命令:
xcopy