排查表单身份验证问题

适用于: Internet Information Services

通常,在 ASP.NET Web 应用程序中使用窗体身份验证时,需要对新请求或正在进行的请求间歇性重定向到应用程序的登录页时出现的问题进行故障排除。 可以通过在开发环境中附加调试器在 Visual Studio IDE 上调试此问题。 然而,在生产环境中,任务变得繁忙且存在问题。 要解决像这样的随机问题,需要记录与问题相关的信息,以便缩小根本原因的范围。

本文简要讨论了 Forms 身份验证的概念。 它还讨论了有关用户被重定向到登录页的各种方案,以及如何捕获与隔离问题相关的数据。 此外,它还讨论了如何实现 IHttpModule 接口来记录窗体身份验证信息。

ASP.NET 窗体身份验证概述

表单身份验证允许你使用自己的代码对用户进行身份验证,然后在 Cookie 或 URL 中维护身份验证令牌。 表单身份验证通过类参与 ASP.NET 页生命周期 FormsAuthenticationModule 。 可以使用该类访问表单身份验证信息和功能 FormsAuthentication

若要使用表单身份验证,请创建一个登录页,用于从用户收集凭据,并包括用于对凭据进行身份验证的代码。 通常,当用户尝试访问受保护的资源(例如需要身份验证的页面)时,将应用程序配置为将请求重定向到登录页。 如果用户的凭据有效,则可以调用类的方法 FormsAuthentication ,以使用适当的身份验证票证(cookie)将请求重定向回最初请求的资源。 如果不希望重定向,只需获取表单身份验证 Cookie 或对其进行设置。 在后续请求中,浏览器使用请求传递身份验证 Cookie,然后绕过登录页。

默认情况下,类 FormsAuthenticationModule 将添加到 Machine.config 文件中。 该 FormsAuthenticationModule 类管理 Forms 身份验证过程。

可以在 Machine.config 文件中看到以下条目

<httpModule> 
  <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />            
</httpModule>

可以使用身份验证配置元素配置表单身份验证,例如设置登录页。 在配置文件中,指定要将未经身份验证的请求重定向到登录页的 URL。

身份验证成功后,模块 FormsAuthenticationModule 会将 User 属性的值设置为对经过身份验证的用户的引用。 下面的代码示例演示如何以编程方式读取表单身份验证用户的标识。

String authUser2 = User.Identity.Name;

使用表单身份验证的一种便捷方法是使用 ASP.NET 成员身份和 ASP.NET 登录控件。 ASP.NET 成员身份允许你存储和管理用户信息,并包括对用户进行身份验证的方法。 ASP.NET 登录搭配 ASP.NET 成员身份使用。 它们封装提示用户输入凭据、验证用户、恢复或替换密码等的逻辑。 实际上,ASP.NET 成员身份和 ASP.NET 登录控件提供对表单身份验证的抽象层。 这些功能取代了你通常必须执行的大部分或全部工作才能使用表单身份验证。

方案

下面是请求重定向到 login.aspx 页的方案:

表单身份验证 Cookie 丢失。

方案 1

登录到网站。 在某些时候,客户端会向服务器发送请求,并且 FormsAuthenticationModule 该类不会接收 Cookie。

方案 2

超过客户端的 Cookie 限制时,表单身份验证 Cookie 也可能会丢失。 在 Microsoft Internet Explorer 中,有 20 个 Cookie 的限制。 计数器达到 20 后,将从客户端的集合中删除前 19 个 Cookie。 如果删除了 ASPXAUTH Cookie,则会在处理下一个请求时重定向到登录页。

方案 3

请求离开客户端后,各个层都会影响正在发送的数据包。 要确定网络设备是否正在删除 Cookie,必须捕获客户端和服务器上的网络跟踪,然后在请求正文中查找 Cookie。 你想要查看客户端请求以确保 Cookie 已发送,并检查服务器跟踪以确保服务器收到了 Cookie。

表单身份验证票证超时

在 ASP.NET 2.0 应用程序中,默认情况下,表单身份验证 timeout 值已更改为 30 分钟。 这意味着,在处于非活动状态 30 分钟后,系统会提示你再次登录。

备注

每次访问网站时,都会重置 30 分钟的窗口时钟。 仅当空闲时,才会有超时。

如果要将值更改为 timeout 更长的时间,可以轻松更改 timeout 本地 web.config 文件中的值( timeout 该值以分钟为单位):

<system.web> 
 <authentication mode="Forms">     
   <forms timeout="120"/>                 
 </authentication>
</system.web>

方案 4

表单身份验证可以在配置文件中定义的属性的值 timeout 之前过期。

如果手动生成表单身份验证票证, timeout 票证的属性将替代配置文件中设置的值。 因此,如果该值小于配置文件中的值,则表单身份验证票证将在配置文件 timeout 属性值之前过期,反之亦然。 例如,假设FORMS超时属性在 Web.config 文件中设置为 30,票证的过期值设置为 20 分钟。 在这种情况下,表单身份验证票证将在 20 分钟后过期,然后必须再次登录。

Event code: 4005
Event message: Forms authentication failed for the request. Reason: The ticket 
supplied has expired.

方案 5

在使用表单身份验证的 ASP.NET 4 Web 应用程序中,事件日志消息显示:

Event code: 4005 
Event message: Forms authentication failed for the request. Reason: The ticket supplied was invalid.

数据收集和故障排除

故障排除方案 1

可以通过在 Microsoft Internet Information Services (IIS)中启用 cookie 日志记录来确定请求是否不包含 Cookie。 为此,请按照以下步骤操作:

  1. 打开 IIS Microsoft 管理控制台 (MMC)。
  2. 右键单击该网站,然后选择“ 属性”。
  3. 选择“网站”选项卡,然后选择“启用日志记录”。
  4. 确保日志格式为 W3C 扩展日志文件格式。
  5. 选择“属性”。
  6. 选择“高级”选项卡,然后选择“扩展属性”。
  7. 在“扩展属性”下,选中“Cookie”和“引用者”(cs(引用者)复选框。

出现此问题后,确定哪个客户端存在该问题以及该客户端的 IP 地址。 筛选该客户端 IP 地址上的 IIS 日志,并查看 <COOKIE> 列。

备注

使用 日志分析器 分析 IIS 日志。

获得来自特定用户的请求列表后,搜索对登录页的请求。 你会知道他们已重定向到此页面,并且你希望在重定向发生之前看到请求。 如果看到类似于以下内容的内容,客户端要么未发送 Cookie,要么在客户端和服务器之间的网络上删除了 Cookie。

备注

除非要创建持久 Cookie,否则第一个请求不太可能具有表单身份验证 Cookie。 IIS 日志将仅显示请求中收到的 Cookie。 成功登录尝试后,第一个请求具有表单身份验证 Cookie。

故障排除方案 2

Microsoft Internet Explorer 符合以下 RFC 2109 建议的最低限制:

  • 至少 300 个 Cookie。
  • 每个 Cookie 至少 4,096 个字节(根据在 Set-Cookie 标头的语法说明中构成 Cookie 非终端的字符大小测量)。
  • 每个唯一主机或域名至少有 20 个 Cookie。

超过客户端的 Cookie 限制时,表单身份验证 Cookie 也可能会丢失。 在 Microsoft Internet Explorer 中,有 20 个 Cookie 的限制。 计数器达到 20 后,将从客户端的集合中删除前 19 个 Cookie。 如果删除了 ASPXAUTH Cookie,则会在处理下一个请求时重定向到登录页。 可以使用 Fiddler 查看 HTTP 请求或响应标头,以查看是否从客户端接收 Cookie。 下载 Fiddler

在客户端计算机上启动 Fiddler 工具,删除现有的 HTTP 跟踪,访问实现表单身份验证的应用程序,并尝试登录到应用程序并观察 Fiddler 上的 HTTP 流量,以查看客户端和服务器之间是否存在表单身份验证 Cookie 的交换。 捕获流量后,双击请求,然后选择“标头以查看 Set-Cookie 标头。 如果跟踪成功的登录名,则会在成功登录的响应中看到 Set-Cookie 标头。

默认情况下,Internet Explorer 可以为每个域最多存储 20 个 Cookie。 如果域中的服务器向客户端计算机发送了 20 多个 Cookie,则客户端计算机上的浏览器会自动丢弃一些旧的 Cookie。

每个 Cookie 由单个名称/值对组成。 该对后面可能是由分号分隔的属性值对。 增加此限制是为了简化必须使用多个 Cookie 的域上的 Web 应用程序的开发和托管。 安装更新 937143 会将 Internet Explorer 可以为每个域存储的 Cookie 数量从 20 个增加到 50 个。 有关详细信息,请参阅 适用于 IT 专业人员的 Internet Explorer 和 Microsoft Edge 常见问题解答(常见问题解答)。

故障排除方案 3

请求离开客户端后,有各种层可能会影响正在发送的数据包(防火墙、代理和负载均衡器)。 若要确定网络设备是否正在删除 Cookie,必须在客户端和服务器上捕获网络跟踪,然后在请求正文中搜索 Cookie。 你可能想要查看客户端请求以确保已发送 Cookie,然后检查服务器跟踪以确保服务器收到了该 Cookie。

客户端请求

这是 GET 在对用户进行身份验证后的请求。 表单身份验证票证信息以灰色突出显示。 这一做法确认 Cookie 信息已离开客户端。 使用网络捕获工具(如 WireShark)时,会看到实际通过适配器的流量。

47 45 54 20 68 74 74 70-3a 2f 2f 6c 6f 63 61 6c   GET http://local
68 6f 73 74 2f 46 6f 72-6d 73 41 75 74 68 4c 6f   host/FormsAuthLo
67 54 65 73 74 2f 57 65-62 46 6f 72 6d 31 2e 61   gTest/WebForm1.a
73 70 78 20 48 54 54 50-2f 31 2e 31 0d 0a 41 63   spx HTTP/1.1..Ac
63 65 70 74 3a 20 69 6d-61 67 65 2f 67 69 66 2c   cept: image/gif,
…Other headers of the GET request…
63 68 65 0d 0a 43 6f 6f-6b 69 65 3a 20 2e 41 53   che..Cookie: .AS
50 58 41 55 54 48 3d 33-43 45 46 39 42 39 41 30   PXAUTH=3CEF9B9A0
43 33 37 41 44 46 36 33-45 36 42 44 33 37 42 36   C37ADF63E6BD37B6
39 43 44 41 32 35 30 30-30 46 38 30 37 32 38 46   9CDA25000F80728F
35 31 43 39 35 36 36 44-31 34 43 35 34 31 34 35   51C9566D14C54145
38 31 43 39 33 45 32 41-30 31 44 44 43 44 45 46   81C93E2A01DDCDEF
32 34 41 31 37 34 32 39-34 31 30 43 30 39 37 34   24A17429410C0974
42 33 45 43 42 30 36 34-32 32 38 45 33 35 33 39   B3ECB064228E3539
39 41 38 32 32 42 33 42-39 33 36 44 46 30 38 46   9A822B3B936DF08F
42 41 42 44 33 45 31 30-32 44 30 30 32 31 30 43   BABD3E102D00210C
32 45 31 33 39 38 30 37-39 42 32 33 35 32 39 46   2E1398079B23529F
34 46 35 44 37 34 41 3b-20 50 72 6f 66 69 6c 65   4F5D74A; Profile
3d 56 69 73 69 74 6f 72-49 64 3d 62 32 34 65 62   =VisitorId=b24eb

服务器端请求

看到到达服务器的请求时,请确保服务器收到客户端发送的相同信息。 如果服务器未收到相同的信息,则需要调查网络上的其他设备,以确定 Cookie 的删除位置。

备注

也有 ISAPI 筛选器删除 Cookie 的实例。 如果确认 Web 服务器已收到 Cookie,但该 Cookie 未在 IIS 日志中列出,请检查 ISAPI 筛选器。 你可能需要删除筛选器才能查看该问题是否得到解决。

故障排除方案 5

  • 如果方案涉及 Web 场,请确保 Web 场中每台服务器上的配置文件对验证密钥和解密密钥具有相同的值,这些密钥分别用于哈希和解密。 若要在场中的所有服务器上保持一致性,请使用以下 machineKey:

    <machineKey validationKey="<yourKey>" decryptionKey="<yourKey>" validation="SHA1" />
    

    有关计算机密钥的详细信息,请参阅 计算机密钥计划应用程序安全性

    若要了解如何生成计算机密钥,请参阅“计算机密钥设置”。

  • timeout比较所有 Web 服务器上这两种表单的值,即身份验证模块和会话模块。

  • 比较服务器场中所有 Web 服务器之间 ASP.NET 4 的 Framework 文件夹下的System.Web.dll版本。 请求的表单身份验证失败。 原因是提供的票证无效。 由于某个 Web 服务器上的 MS .NET Framework 4 缺少可靠性更新 1,因此会发生此情况。

  • 在缺少 MS .NET Framework 4 kb2533523 的可靠性更新 1 的服务器上安装该更新,然后重新启动服务器。 问题已修复。 有关详细信息,请参阅 .NET Framework 4 的可靠性更新 1。

详细信息

第三方信息免责声明

本文中提到的第三方产品由 Microsoft 以外的其他公司提供。 Microsoft 不对这些产品的性能或可靠性提供任何明示或暗示性担保。