Chrome 用户离开页面后 .ASPXAUTH cookie 丢失
结论
.ASPXAUTH 很可能不是付款网站删除的。更常见的是以下两种情况:
- 登录时创建的是会话 Cookie。浏览器关闭或恢复会话后,不保证继续保留它。
- Cookie 仍保存在浏览器中,但付款回跳时受域名、路径、HTTPS 或跨站请求限制,没有随请求发送。
仅凭 Chrome 20.0.1132.47 这个版本号,无法认定问题来自浏览器缺陷。也不要把”关闭并重新打开 Chrome 后 Cookie 仍然存在”当作可靠依据。会话 Cookie 没有明确的持久化期限,Chrome 的会话恢复功能可能暂时保留它,但它仍不是永久 Cookie。
先确认 Cookie 是丢失还是没有发送
检查付款回调请求中的 Cookie 请求头,并核对回跳地址:
- 登录地址和回跳地址是否使用相同的主机名,例如
www.example.com和example.com并不相同。 - 是否从 HTTPS 回到了 HTTP。
.ASPXAUTH的Domain、Path和Secure属性是否允许浏览器在回跳地址上发送它。- 付款平台使用普通的
GET跳转,还是通过跨站表单POST返回。 - 浏览器中是否还能看到
.ASPXAUTH,但请求头中没有它。
服务端可以临时记录是否收到了 Cookie,但不要记录 Cookie 的实际值:
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null)
{
// 只记录缺失事实以及必要的请求信息,
// 不要把认证 token 写入日志。
}
将登录 Cookie 明确设为持久 Cookie
如果付款过程中允许用户关闭窗口、重启浏览器,或者会打开新的浏览器会话,就不该使用会话 Cookie。创建登录 Cookie 时,应将 isPersistent 设置为 true:
FormsAuthentication.SetAuthCookie(userName, true);
如果是否记住登录状态由用户决定,可以直接传入对应选项:
FormsAuthentication.SetAuthCookie(
userName,
model.RememberMe
);
如需精确控制过期时间,可以显式创建认证票据:
DateTime issuedAt = DateTime.Now;
DateTime expiresAt = issuedAt.AddHours(2);
FormsAuthenticationTicket ticket =
new FormsAuthenticationTicket(
1,
userName,
issuedAt,
expiresAt,
true,
string.Empty,
FormsAuthentication.FormsCookiePath
);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
encryptedTicket
);
cookie.HttpOnly = true;
cookie.Path = FormsAuthentication.FormsCookiePath;
cookie.Expires = expiresAt;
// 仅当站点全程使用 HTTPS 时启用。
cookie.Secure = true;
Response.Cookies.Add(cookie);
还要检查 web.config 中的 Forms Authentication 配置:
<authentication mode="Forms">
<forms
loginUrl="~/Account/LogOn"
timeout="120"
slidingExpiration="true"
requireSSL="true"
path="/" />
</authentication>
timeout 控制认证票据的有效期,但不会自动将通过 SetAuthCookie(userName, false) 创建的会话 Cookie 转为持久 Cookie。
检查域名、路径和 HTTPS
假设用户在以下地址登录:
https://www.example.com/
而付款平台返回的是:
https://example.com/payment/complete
仅属于 www.example.com 的 Cookie 不会发送给 example.com。最稳妥的处理方式,是让登录入口和付款回调使用完全相同的协议、主机名和端口。
还需注意:
Path=/account的 Cookie 不会发送到/payment/complete。- 带有
Secure属性的 Cookie 不会通过 HTTP 发送。 - 不要为了绕过问题随意扩大
Domain,尤其不要让不受信任的子域共享认证 Cookie。
现代浏览器还需要检查 SameSite
Chrome 20 所处的年代早于后来的 SameSite 默认策略,因此不能据此认定当时的问题由 SameSite 引起。但如果该系统现在仍在运行,而付款平台通过跨站 POST 返回,现代浏览器可能不会发送 SameSite=Lax 或配置不正确的认证 Cookie。
这类流程通常需要:
SameSite=None; Secure
旧版 ASP.NET MVC/.NET Framework 是否支持 SameSite,取决于实际的框架版本和补丁状态,不能假定 MVC1 自带完整支持。如果无法升级,应优先调整付款回跳流程,使其不依赖认证 Cookie,不要手工拼接可能不兼容的 Cookie 属性。
付款结果不要只依赖 .ASPXAUTH
即使将 Cookie 改为持久 Cookie,付款确认也不应完全依赖用户是否仍处于登录状态。更可靠的流程是:
- 跳转到付款平台前创建本地订单,并生成不可预测的关联标识。
- 将订单号或签名后的
state随付款请求发送。 - 回跳时根据该标识查找订单。
- 通过付款平台的服务端通知或查询接口验证支付状态。
- 即使用户 Cookie 缺失,也要完成订单入账,再要求用户重新登录查看结果。
不要直接信任通过未经签名的 URL 参数传入的用户 ID、金额或”支付成功”标记。
注意事项
- 会话恢复后 Cookie 仍然存在,只是浏览器行为,并不代表浏览器承诺持久保存会话 Cookie。
- 浏览器插件或隐私设置确实可能清理 Cookie,但没有复现证据时,不应将其视为主要原因。
- 不要在日志、查询字符串或错误页面中输出
.ASPXAUTH的值。 - 延长认证有效期会增加 Cookie 被窃取后的风险,应同时使用 HTTPS、
HttpOnly、合理的过期时间和重新认证机制。 - 排查时,应按照浏览器版本、回跳方法、回跳主机名以及是否收到
Cookie请求头分类,不要只统计用户最终是否仍处于登录状态。
备注:内容仅供参考。
