2015-11-06 55 views
2

我有一個使用表單身份驗證的ASP.NET Web應用程序。我們在10月25日凌晨1點 - 凌晨2點在我們的直播網站上看到了一些奇怪的行爲(在英國,DST於2015年10月25日凌晨2點結束,時鐘又回到了一個小時),所有用戶都以簽名認證導致DST的奇怪表單身份驗證過期行爲結束

protected void Application_BeginRequest(object sender, EventArgs e) 
{ 
    HttpCookie cookie = Request.Cookies["MyCookie"]; 

    FormsAuthenticationTicket ticket; 
    try 
    { 
     ticket = FormsAuthentication.Decrypt(cookie.Value); 
    } 
    catch 
    { 
     this.RedirectDueToError(ErrorView); 
     return; 
    } 

    if (ticket == null) { return; } 

    if (ticket.Expiration < DateTime.Now) 
    { 
     this.RedirectDueToError(TimeoutView); 
    } 
} 

在Web.config包含:由下面的代碼過期

<authentication mode="Forms"> 
    <forms name="MyCookie" timeout="40" requireSSL="false"/> 
</authentication> 

我複製一個測試服務器上的問題,可以看到問題的凌晨1點和凌晨2點之間發生之前以DST結尾。當時間到達凌晨2點,並自動將時間恢復到凌晨1點,問題就解決了。

在我的測試過程中,我添加了一些額外的日誌記錄以確定在故障點(也就是剛創建身份驗證票證後)的ticket.ExpirationDateTime.Now的值。結果表明:

結束此前DST:
服務器時間:0點53分39秒
DateTime.Now = 0點53分39秒
ticket.Expiration =一點33分37秒(正確)

之前DST結束:
服務器時間:1時25分08秒
DateTime.Now = 1時25分08秒
ticket.Expiration = 1時05分08秒(錯誤)

後DST結束:
服務器時間:1時35分06秒
DateTime.Now = 1時35分06秒
ticket.Expiration = 2時15分06秒(正確)

因此,DST結束之前,似乎在一小時,從FormsAuthenticationTicketExpiration屬性返回的時間是一小時後。我瞭解到期時間在內部存儲爲UTC,但Expiration媒體資源是當地時間,並且懷疑轉化中存在問題。

任何想法,爲什麼會這樣?代碼問題?服務器問題?

+0

請參閱此處的註釋(http://www.asp.net/web-forms/overview/older-versions-security/introduction/forms-authentication-configuration-and-advanced-topics-vb)。這似乎是這種行爲是由設計? –

+1

我也讀過這個鏈接。它提到了時鐘前進,但沒有提到DST結束。在我的情況下,從凌晨1點到凌晨2點登錄的每個人都會馬上退出,因爲到期時間已經過去了。當然,這不能通過設計? –

回答

1

問題的癥結就在這裏:

if (ticket.Expiration < DateTime.Now) 

此更改爲:

if (ticket.Expiration.ToUniversalTime() < DateTime.UtcNow) 

或者更好的,到這一點,這確實在內部同樣的事情:

if (ticket.Expired) 

問題實際上是詳細的in the comments found in the MSDN reference sources

基本上歸結爲DateTime結構的設計。兩個DateTime對象的比較僅考慮它的Ticks值,而不考慮它的Kind,因此它不考慮DST或時區。

此外,我通常建議不要使用ToUniversalTime,但在這種特殊情況下,它可以。