選單
GSS 技術部落格
在這個園地裡我們將從技術、專案管理、客戶對談面和大家分享我們多年的經驗,希望大家不管是喜歡或是有意見,都可以回饋給我們,讓我們有機會和大家對話並一起成長!
若有任何問題請來信:gss_crm@gss.com.tw
4 分鐘閱讀時間 (868 個字)

Forms AuthenticationTicket SlidingExpiration 過期問題

Forms AuthenticationTicket SlidingExpiration 過期問題


前陣子同仁分享一個 Form Authentication Ticket 過期的問題(為什麼我的 APS.Net Form Authentication 在 timeout 時間還沒到前就失效了)。

如果 timeout 時間設定為 20 分鐘,而 Ticket 是 1:00:00 產生的,到期時間是 1:20:00。

如果設定 SlidingExpiration , 到期的時間會在每次回 Server 就更新嗎?



Timeout 時間跟你想的不一樣嗎?

我們可以看 MSDN 上的說明「FormsAuthentication.SlidingExpiration」,

如果提出要求,而且一半以上的逾時間隔已經經過滑動期限,重設為有效的驗證 cookie 的到期時間。
以下面圖來看(timeout設為4分鐘),就是使用者要在 紅色時間區段中有對 Server Request 過,才會更改「過期時間」。


如果使用者剛好只在綠色時間區段中 Request Server,

然後在 06:28:14 後去 Request Server , 就會 Timeout 了哦!

那有什麼解法呢? 同事的解法就是設定成 Double 的時間,

例如原本設定 20 分鐘 timeout,就設定成 40 分鐘 Timeout。

另一個方式,就是手動去更改 Ticket 的過期時間。

實作

1.建立一個 Web Forms 專案

1.1.建立 Login.aspx (登入後,切到 Default.aspx)
Login.aspx
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title></head><body> <form id="form1" runat="server"> <div> <asp:TextBox runat="server" ID="txtUserId"></asp:TextBox> <asp:Button runat="server" ID="btnLogin" Text="Login" OnClick="btnLogin_OnClick"/> </div> </form></body></html>
Login.aspx.cs
protected void btnLogin_OnClick(object sender, EventArgs e)
{
FormsAuthentication.RedirectFromLoginPage(txtUserId.Text,false);
}
1.2.建立 Default.aspx (列出 Ticket 相關資訊,並更新 Ticket 的過期時間)

Default.aspx
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title></head><body> <form id="form1" runat="server"> <div> <asp:ListBox ID="lsIdentityInfos" runat="server"></asp:ListBox> <hr/> <asp:Button runat="server" ID="btnAddIdentity" Text="Add Identity Info" OnClick="btnAddIdentity_OnClick"/> </div> </form></body></html>
Default.aspx.cs
public partial class Default : System.Web.UI.Page{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
FormsAuthenticationTicketInfo();
}



protected void btnAddIdentity_OnClick(object sender, EventArgs e)
{
FormsAuthenticationTicketInfo();
}

void FormsAuthenticationTicketInfo()
{
var identityInfos = new StringBuilder();
FormsAuthenticationTicket ticket = ((FormsIdentity)Context.User.Identity).Ticket;
var timeoutValue = (TimeSpan)(ticket.Expiration - ticket.IssueDate);
identityInfos.AppendLine($"Timeout:{timeoutValue}");
identityInfos.AppendLine($",IssueDate:{ticket.IssueDate.ToString("hh:mm:ss", null)}, Expiration:{ticket.Expiration.ToString("hh:mm:ss", null)}");
var now = DateTime.Now;
identityInfos.AppendLine($",Now:{now.ToString("hh:mm:ss", null)}");
//var span = now - ticket.IssueDate; //var span2 = ticket.Expiration - now; //identityInfos.AppendLine($"now - ticket.IssueDate:{span}, Expiration - now:{span2}"); lsIdentityInfos.Items.Add(identityInfos.ToString());
//var newTicket = FormsAuthentication.RenewTicketIfOld(ticket); //Response.Write($"{newTicket.Expiration.ToString("hh:mm:ss", null)}"); }

protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (Request.IsAuthenticated && Context.User.Identity is FormsIdentity)
{
//原本的 Ticket var orgTicket = ((FormsIdentity)Context.User.Identity).Ticket;
//取出 Timeout 的值 var timeoutValue = (TimeSpan)(orgTicket.Expiration - orgTicket.IssueDate);

var now = DateTime.Now;
//重新再計算新的過期時間 var newExpiration = now + timeoutValue;
//建立一個新的 Ticket var newTicket = new FormsAuthenticationTicket(orgTicket.Version, orgTicket.Name, now, newExpiration, orgTicket.IsPersistent, orgTicket.UserData);

if (newTicket.Expiration > orgTicket.Expiration)
{
// 建立 FormsAuthentication Cookie HttpCookie objCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(newTicket));
// 蓋掉舊的 Cookie Response.Cookies.Add(objCookie);
}
}
}
}
註:我是在 Page 的 OnPreRender 去更新過期時間,您也可以將它放在 底層 Class 中,或是在 Global.asax 的 Application_AuthenticateRequest 中哦!

 

2.Web.config 設定使用 Forms Authentication

在 web.config system.web 區段中加入
<authentication mode="Forms">  <forms loginUrl="login.aspx"		 name=".rmau" 
slidingExpiration="true"
timeout="4" />
</authentication><authorization> <deny users="?"/></authorization>
當每次 Request Server 後,都會重新設定 Ticket 的過期時間哦! 如下,


測試專案: AuthenticationTicket-SlidingExpiration

參考資料

為什麼我的 APS.Net Form Authentication 在 timeout 時間還沒到前就失效了
FormsAuthentication.SlidingExpiration
Manually sliding Forms AuthenticationTicket expiration
用SonarQube來監控SoftwareQuality-1-簡介
使用 Botkit 來實作 Facebook 的機器人(BOT)

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/05/02, 週四

Captcha 圖像