我们在验证csrf令牌时遇到了一个奇怪的情况。下面是用字母替换标记的事件序列:
-
用户注销。被重定向到主页。
Session.Abandon();
FormsAuthentication.SignOut();
-
使用新会话id(s1)和新csrf令牌(t1)创建新会话。
protected void Session_Start(object sender, EventArgs e)
{
Response.Cookies["ASP.NET_SessionId"].Secure = true;
Token = NewToken();
}
-
主页加载并触发js ajax请求,该请求携带用于验证的令牌(t1)。从检查中,我们知道由于某种原因,这个请求带有
空白的
ASP.NET会话ID cookie(
ASP.NET_SessionId=;
)当它应该有会话id(s1)时。因此,它被视为后端上的一个新会话,并为此请求重复步骤2。后端现在有了新的会话id(s2)和新的令牌(t2)。
-
后端继续为ajax请求提供服务。它将令牌(T1)与令牌(T2)进行比较,但失败。
-
刷新页面或导航到另一个页面后,网站上的后续调用成功,没有问题。ajax请求带有asp.net会话id cookie,一切都按预期工作。它们在会话id(s1)和令牌(t1)下执行。
我们已设法部分追踪到
ASP.NET_SessionId
Cookie设置为
HTTP Only
:
Response.Cookies["ASP.NET_SessionId"].Secure = true;
如果我们删除它,它可以同时处理注销后的第一个请求和随后的请求。这个
ASP.NET会话ID
所有ajax调用都会发送cookie。
我们[显然]想保护cookies的安全,所以删除
Secure = true
不是一个选择。
为什么注销后第一页加载ajax请求
不
为
ASP.NET会话ID
Cookie但是后续的请求呢?就像
ASP.NET会话ID
Cookie在JS中对于加载后的初始请求没有准备或可用,但可以在后续请求(导航/重新加载)中读取。