排查 ASP.NET 中的常见权限和安全相关问题

本文介绍如何排查 ASP.NET 中的常见权限和安全相关问题。

原始产品版本: ASP.NET
原始 KB 编号: 910449

有用的工具

在尝试修复中断的任何内容之前,需要熟悉一些工具,这些工具有助于缩小问题的范围。 在本例中,我们将对 FileMon、RegMon 和安全审核等工具感兴趣。 有关 FileMon 的详细信息,请参阅 适用于 Windows v7.04 的 FileMon

有关 RegMon 的详细信息,请参阅 Windows Sysinternals

向下钻取以隔离问题

  • 应用程序是否曾经工作过? 如果是,那么哪些更改可能使应用程序中断? 软件更新或安全更新可能在服务器上应用。 代码推出也可能导致此问题。
  • 简单的 .html 和.asp页是否从 IIS 提供?
  • 应用程序是否已迁移到其他版本的 IIS?
  • 服务器上的其他 ASP.NET 应用程序是否失败并出现相同的错误? 这是唯一失败的应用程序吗?
  • 此问题是针对所有用户还是仅特定用户发生?
  • 此问题是在 Web 服务器上本地浏览时可重现的,还是仅对少数客户端可重现?
  • 如果使用模拟,则模拟用户是否具有对资源的必要访问权限?

上述问题对于诊断问题非常有用。 如果你在任何 ASP.NET 论坛上发布你的问题,并且你已经有了其中大多数问题的答案,那么你很可能得到一个指向你的问题的快速指针或解决方案。 关键是发布整个 ASP.NET 堆栈跟踪错误(如果适用),而不是说“我在尝试运行 ASP.NET 应用程序时收到拒绝访问错误。 任何人都可以帮忙吗?当某人可以看到完整的错误消息时,查看堆栈跟踪并为你提供指针要容易得多。 因此,你需要问问自己...

确切的错误消息是什么?

我们询问客户的第一个问题是,“确切的错误消息是什么?如果对 Microsoft .NET Framework引发的错误消息有明确说明,则可以跳过此部分。 如果应用程序屏蔽了实际错误消息,并改为提供了一条友好的错误消息,例如,“发生了意外错误。 有关详细信息,请与网站管理员联系,“对任何人都没有太大用。 下面是几个步骤,可帮助你获取实际的错误消息。

  • 在应用程序目录中找到并打开 Web.config 文件,并将 customErrors 更改为 mode=“Off”。 保存文件,并重现问题。

  • 执行上述步骤后,由于应用程序开发人员执行的自定义事件/错误处理,可能仍无法看到实际的错误消息。 可以尝试在 Global.asax 文件中查找 Application_Error 事件,并注释掉使用该 Server.Transfer("Errors.aspx") 函数转到自定义错误页的任何代码。

    //Global.asax 
    void Application_Error(object sender, EventArgs e) 
    { 
        // Code that runs when an unhandled error occurs 
        //Server.Transfer("Errors.aspx"); 
    }
    

收到实际错误消息后,请阅读它以确定错误是由本地资源或远程资源缺少权限导致,ASP.NET 应用程序正在尝试访问。

提示

你可以与开发人员联系,了解如何查看实际的错误消息。 开发人员可能会将其记录到文件或收到电子邮件通知。 请始终记住备份要更改的任何文件。 使用可用的备份,始终可以回滚任何更改。

出现此问题的原因是缺少对 ASP.NET 应用程序尝试访问的本地资源的权限

如果由于自定义错误消息而无法获取问题的明确说明,请运行 FileMon 并重现问题。 停止捕获并将其另存为 FileMon.xls 并在 Microsoft Excel 中打开文件。 在“ 数据 ”菜单上,单击“ 筛选器”,然后单击“ 自动筛选” 以使用 Excel 的筛选功能。 现在,选择列中 F 的下拉列表,并查找“拒绝访问”错误。

示例 FileMon 输出如下所示。

10381 1:01:11 PM w3wp.exe:2320 OPEN C:\winnt\microsoft.net\framework\v1.1.4322\Temporary ASP.NET Files\sessiontest\8832e585\275ec327\global.asax.xml 
ACCESS DENIED NT 
AUTHORITY\NETWORK SERVICE

从筛选结果中可以看到,我们缩小了问题原因的范围。 FileMon 显示 NT AUTHORITY\NETWORK 服务帐户缺少对文件夹的 C:\Winnt\Microsoft.net\Framework\v1.1.4322\Temporary ASP.NET Files NTFS 权限。 这应该直接解决。

提示

一个很好的步骤是将 ASP.NET 进程帐户更改为管理员帐户,以查看它是否解决了问题。 在 IIS 6.0 及更高版本中,将 IIS AppPool 标识更改为“本地系统”,以查看应用程序是否正常工作。

注意

这不应用作解决方案,而只能用作故障排除步骤。

大多数人倾向于重新安装 Microsoft .NET Framework甚至会重新安装操作系统。 这不是建议的故障排除步骤,也不保证问题不会再次发生。 我将提供一个这样的示例。 间歇性问题通常很难隔离和故障排除。 在这种情况下,客户的应用程序将正常工作几个小时,然后突然失败,并出现以下错误。 客户已尝试重新安装.NET Framework以及操作系统。 这似乎修复了几天的问题,但随后它再次出现。

运行 FileMon 时未显示任何 “拒绝访问” 错误。 ASPNET 帐户的所有必要权限都已到位。 从问题中恢复的唯一方法是重新启动该箱。 即使 IIS 重置也无济于事。 你在想“啊,Microsoft 软件总是需要重新启动才能恢复?”嗯,你错了!

此处的关键是仔细查看错误消息。 此错误明确表示“无法打开文件进行写入”,而不是常见的 ACCESS DENIED 错误,因此我认为是其他某个进程锁定文件或文件夹,不允许 ASP.NET 写入。 重新启动会终止另一个进程,并且 ASP.NET 应用程序重新开始工作,直到恶意进程再次锁定文件,这是有道理的。 合乎逻辑的是关闭服务器上运行的所有防病毒程序、第三方间谍软件或任何其他文件监视软件。 我不想指出任何特定的第三方软件。 但是,一般来说,防病毒软件会给 IIS 和 ASP.NET 应用程序带来很多麻烦。 防病毒软件引起的另一个已知问题是,当接触 Bin 文件夹或 .config 文件时,AppDomain 回收导致会话丢失。

提示

关闭第三方服务的最简单方法是:

  1. 单击“ 开始”,单击“ 运行”,然后键入 msconfig
  2. 选择“服务”,检查隐藏所有 Microsoft 服务
  3. 单击“ 全部禁用 ”以停止第三方服务。
  4. 单击“ 开始”,单击“ 运行”,然后键入 iisreset 以将 CLR 重新加载到工作进程中。

监视应用程序以查看问题是否再次出现。 如果运行多个防病毒程序,请使用试用版和错误方法确定导致问题的特定程序。

注意

如果 100% 的时间可以重现相同的错误,则防病毒软件可能不是原因。 此错误可能还有其他原因。 尝试创建一个简单的 ASP.NET 测试应用程序,以隔离Test.aspx页是否发生相同的错误。 如果是,请验证 ASP.NET 所需的访问控制 Lists (ACL) 是否已全部到位。

请参阅 ) ASP.NET 必需访问控制 Lists (ACL

提示

文件夹 %SystemRoot%\Assembly 是全局程序集缓存。 不能直接使用 Windows 资源管理器编辑此文件夹的 ACL。

请改用命令提示符并运行以下命令:

cacls %windir%\assembly /e /t /p domain\useraccount:r

或者,在使用 Windows 资源管理器之前,请使用以下命令注销 Shfusion.dll,以便通过 GUI 授予权限:

C:\WINDOWS\Microsoft.NET\Framework\VersionNumber>regsvr32-u shfusion.dll

使用 Windows 资源管理器设置权限后,使用以下命令重新注册 Shfusion.dll:

C:\WINDOWS\Microsoft.NET\Framework\VersionNumber>regsvr32 shfusion.dll

由于缺少 ASP.NET 应用程序正在尝试访问的远程资源的权限,因此会出现问题

当 ASP.NET 应用程序访问远程资源(如 Microsoft SQL Server 或通用命名约定 (UNC) 共享)时,可能会出错。 此外,在远程资源上设置的很多内容可能不正确。 需要解决这些问题才能使资源正常工作。

第一步是查看是否可以通过 Windows 资源管理器连接到远程服务器。

  1. 在远程服务器上,创建名为 Test 的文件夹。 在“测试”文件夹的“共享和安全”选项卡上,添加域/帐户以及 ASP.NET 应用程序使用的进程帐户,并赋予它们“完全控制”。

  2. 在 IIS 服务器上,使用域/帐户登录,依次单击“ 开始”和“ 运行”,然后键入远程服务器的 UNC 共享路径: \\RemoteServerName*\Test

    如果无法访问此文件夹,请与网络管理员联系以解决此问题。 只有这样,ASP.NET 应用程序才能访问共享。

  3. 使用以下代码创建名为 CreateUNCFile.aspx 的文件,并将该文件保存在应用程序目录中。

    <%@ Page Language="vb" %>
    <%@ Import Namespace="System.IO" %>
    <html>
    <head>
    <title>Writing to a Text File</title>
    <script runat="server">
        Sub WriteToFile(ByVal sender As System.Object, ByVal e As System.EventArgs)
            Dim fp As StreamWriter
                fp = File.CreateText("\\<RemoteServerName>\Test\" & "test.txt")
                fp.WriteLine(txtMyFile.Text)
                lblStatus.Text = "The File Successfully created! Your ASP.NET process is able to access this remote share"
                fp.Close()
        End Sub
    </script>
    
    </head>
    <body style="font: 10pt verdana">
                <h3 align="center">Creating a Text File in ASP.NET</h3>
        <form id="Form1" method="post" runat="server">
                            Type your text:
                            <asp:TextBox ID="txtMyFile" TextMode="MultiLine" Rows="10" Columns="60" Runat="server" /><br>
                            <asp:button ID="btnSubmit" Text="Create File" OnClick="WriteToFile" Runat="server" />
                            <asp:Label ID="lblStatus" Font-Bold="True" ForeColor="#ff0000" Runat="server" />
        </form>
    </body>
    </html> 
    
  4. 确保在以下代码行中修改 <RemoteServerName>

    fp = File.CreateText("\\<RemoteServerName>\Test\" &"test.txt")
    

    以便它反映远程服务器的名称。

  5. 打开 Windows Internet Explorer,并从 IIS 服务器以外的客户端计算机浏览到 http://**IISServerName**/**AppName**/CreateUNCFile.aspx

  6. 如果成功创建 Test.txt 文件,则 ASP.NET 应用程序可以向远程资源进行身份验证。

  7. 如果从 Internet Explorer 客户端浏览器创建文件失败,但如果从 IIS 服务器本身浏览到同一页,则很可能遇到“双跃点”方案。 如果使用自定义生成的 Web 部件访问需要用户身份验证和授权的远程资源,则可能会遇到“双跃点”问题。 若要访问远程资源,可能需要向资源提供最终用户的凭据,以便资源的输出仅限于最终用户有权访问的数据。

上述步骤假定已在 IIS 中打开 NTLM 身份验证。 基本身份验证不使用 Kerberos。

有关详细信息,请参阅 排查 Internet Explorer 中的 Kerberos 故障

有关 IIS 身份验证方法的详细信息,请参阅 Visual Studio 2003 已停用技术文档

提示

如果可以连接到远程 UNC 共享,但无法从 ASP.NET 应用程序连接到运行SQL Server的远程服务器,则可能必须检查或设置服务主体名称 (SPN) SQL Server。 尝试在 IIS 中仅为应用程序启用基本身份验证,并查看是否可以连接到运行SQL Server的远程服务器。

出现“服务器应用程序不可用”错误消息的许多其他原因。 事件日志是获取有关问题原因的更多详细信息的最佳选择。

IIS 日志在出现 IIS 身份验证相关错误时很有用。

需要查找的是此特定错误的状态和子状态代码。

2006-10-12 22:47:28 W3SVC1 65.52.18.230 GET /MyAPP/login.aspx - 80  
MyDomain\UserID_91 65.52.22.58 Mozilla/4.0+  
(compatible;+MSIE+6.0;+Windows+NT+5.2;+SV1;+.NET+CLR+1.1.4322;+.NET+CLR+2.0.50727;+InfoPath.1) 401 3 5

我们看到子状态为 3 的 401,指示“由于资源上的 ACL 而未授权”。

这表示缺少对文件或文件夹的 NTFS 权限。 即使您尝试访问的文件的权限正确,也可能会发生此错误,但其他 SYSTEM 和 IIS 文件夹上可能缺少默认权限和用户权限。 例如,如果IUSR_ComputerName帐户无权访问 C:\Winnt\System32\Inetsrv 目录,则可能会看到此错误。

提示

单击 “开始”,单击“ 运行”,然后键入“日志文件”以打开包含 IIS 日志的文件夹。 或者,在 IIS 中网站的属性页上,单击“ WebSiteName ”选项卡,然后在“ 活动日志格式”下,单击“ 属性 ”以查看日志文件目录和名称。

此处的另一个关注点是状态代码 5。 可以使用 net helpmsg 命令获取有关此状态代码的详细信息:

C:\Documents and Settings\User> net helpmsg 5

访问被拒绝。

让我们尝试另一个常见状态代码,代码 50:

C:\Documents and Settings\User> net helpmsg 50

不支持该请求。

提示

每当收到另一条泛型臭名昭著的“500 内部服务器错误”消息时,最好禁用友好的 HTTP 错误消息,以便收到错误的详细说明。 不要忘记查看事件查看器,因为它可能还包含更多信息。

其思路是使用所有可用的记录信息来获取有关当前问题的最大详细信息。

资源

有关更多信息,请参阅: