

ASP.NET Form 驗證 ASPXAUTH Cookie 行為深入觀察
source link: https://blog.darkthread.net/blog/aspxauth-cookie-timeout/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ASP.NET Form 驗證靠 .ASPXAUTH Cookie 識別身分,它是一段用 Machine Key 加密並簽名的內容,包含身份識別、有效期限等資訊。這段機制在 WebForm 與 ASP.NET MVC 是共用的,因此設定相同的 Machine Key,ASP.NET WebForm 與 MVC 也可共用登入身分。基於這個原理,Machine Key 的保管便格外重要,一旦外流,駭客便可輕易冒充任何登入者。
以上是我對 ASPXAUTH 的全部理解。今天偵察問題時,發現 ASPXAUTH 有個重設行為,是我以前沒注意到的。在某些情況下,ASP.NET 會重設 .ASPXAUTH Cookie,如下圖,Request 已有 .ASPXAUTH Cookie 9AD515A...,ASPX 回應包含 Set-Cookie 將 .ASPXAUTH 改為 C8B7DE71...,之後瀏覽器將改用 C8B7DE71...:
我懷疑這是 FormsAuthentication SlidingExpiration 的行為,當使用者 SlidingExpiration 時間一半到逾期前這段時間存取網站,有效期限將自動延長,而延長期限的動作便是透過更新 .ASPXAUTH Cookie 完成。參考來源 Sliding expiration resets the expiration time for a valid authentication cookie if a request is made and more than half of the timeout interval has elapsed. )
於是我設計了一個實驗,以便深入觀察 .ASPXAUTH 的運作。
借用之前的程式範例,我寫了一支 ChkCookie.aspx,用以顯示登入帳號、.ASPXAUTH Cookie 及解密還原出的 FormsAuthenticationTicket 物件(建立時間及有效期限),另外再顯示目前時間及 FormsAuthenticationTicket 的壽命方便對照。按下 Reload 時會帶入?t=FormsAuthenticationTicket建立秒數
以利識別:
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web.Security" %>
<script runat="Server">
protected string Info { get; set; }
protected int Age { get; set; }
void Page_Load(object sender, EventArgs e)
{
var req = Request;
var resp = Response;
var sb = new StringBuilder();
if (req.IsAuthenticated)
sb.AppendLine("User=" + User.Identity.Name);
else
sb.AppendLine("Not Authenticated");
foreach(string key in req.Cookies.AllKeys)
{
var val = req.Cookies[key].Value;
val = val.Substring(0, Math.Min(20, val.Length));
sb.AppendLine("* " + key + "=" + val);
}
var authCookie = req.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie == null)
sb.AppendLine("No cookie - " + FormsAuthentication.FormsCookieName);
else {
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
sb.AppendLine("Ticket.Expired=" + authTicket.Expired);
sb.AppendLine("Ticket.IssueDate=" + authTicket.IssueDate.ToString("HH:mm:ss"));
sb.AppendLine("Ticket.Expiration=" + authTicket.Expiration.ToString("HH:mm:ss"));
Age = Convert.ToInt32((DateTime.Now - authTicket.IssueDate).TotalSeconds);
}
Info = sb.ToString();
}
</script>
<!DOCTYPE html>
<html>
<head></head>
<body>
<div>
<button onclick="location.href=location.href.split('?')[0]+'?t='+cnt">Reload</button>
<span id=t></span>
</div>
<pre><%=Info%></pre>
<script>
var cnt = <%=Age%>;
setInterval(function () {
document.getElementById('t').innerText =
new Date().toTimeString().split(' ')[0] + ' (' + cnt + 's)';
cnt++;
}, 1000);
</script>
</body>
</html>
FormsAuthenticationTicket 時效可由程式或 web.conf forms timeout 設定,單位為分鐘:
<authentication mode="Forms">
<forms loginUrl="Login.aspx" timeout="1" />
</authentication>
經過一連串實驗,我觀察到幾件事:
- timeout 會決定 FormsAuthenticationTicket 的有效期限,例如:timeout="1" 時,IssueDate 與 Exipration 就相隔一分鐘:
- 在一分鐘內多次 Reload 並觀察 Cookie 異動狀況,FormsAuthenticationTicket 壽命超過一半(30-60 秒)後存取,ASP.NET 會重設 .ASPXAUTH。如下展示,27、29 秒時只有要求 Cookie,30 秒那次回應更新 .ASPXAUTH,從 32 起改用新 Cookie (40AD63...)
- 若 FormsAuthenticationTicket 壽命一分鐘,30-60 間要存取才有延壽效果。如下圖,13、17、26 秒有重新整理,但 30-60 間無活動,67 秒再存取時登入身分便失效。另外,已失效的 .ASPXAUTH Cookie 會被 ASP.NET 剔除,即使瀏覽器有送出 Cookie,也不會出現在 Request.Cookies:
- 設定
<forms loginUrl="Login.aspx" timeout="1" slidingExpiration="false" />
後,30-60 秒的存取就不會有 Set-Cookie 動作:
透過以上實驗,我們對 .ASPXAUTH 的行為就有更深一層的認識囉。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK