2015年2月6日 星期五

物件導向不應該犯的錯,竟導致 ASP.NET Identity lockout 機制失敗

會犯這種錯,當然是錯誤的示範啦。

歷史

首先,我們使用了 TDD 的開發方式,所以先寫測試,再寫商業邏輯。此時,還沒有網頁的需求。
然後,再加上網頁後,遵循 Agile 的精神,對使用者重要的先寫,所以仍以商業需求為主。此時用的是 EF Code First + MemberShip Provider 做登入驗證。

當然,使用者對他要求的商業需求已經滿意了。最後使用者常見的非功能需求,「要求登入失敗多次後,鎖定帳號 5分鐘」這種安全性的需求時,我們早就準備好了 ASP.NET identity (傳著等)。

等等!竟然鎖定機制失效了!故意打入正確帳號但錯誤的密碼,只見 AccessFailedCount 完全不聽使喚,全然不會遞增。

原因

因為我們之前已經有自訂的 ApplicationUser 類別,而類別中已有 Email 屬性。而最後為了使用 ASP.NET Identity,自然地會將我們自訂的 ApplicationUser 類別繼承 IdentityUser.

此時,ApplicationUser 如下圖

image

看起來沒什麼狀況吧。咦?Email 屬性下有一點小波浪?反正是 Warning,應該不會有什麼問題。
就這個念題,讓我浪費了半天的好光陰.

仔細看一下提示訊息,the keyword ‘new’ is required on ‘Email’ because ….,這個意指著在 c# 中,如同上面的程式碼,代表著「身為 ApplicationUser 的 Email 與身為 IdentityUser 的Email 是不相同屬性」, 見下面的單元測試。這是dotnet framework 較為特殊的地方。而這個地方將導致 ASP.NET Identity Lockout 機制失敗。

image

解法

只需要簡單地在ApplicationUser 將重複的 Email 屬性移除, 或者加上 override 指示詞就解決了這個看來完全不相干的問題。

結論

要發生我遇到的狀況,其實很簡單。建立一個MVC新專案,找到 ApplicationUser,再加上那個沒有 override 的 Email 屬性,就可以還原我碰到的問題了。

這代表著:連 warning 都不可以忽略!

2 則留言:

Will 保哥 提到...

Visual Studio 2013 Update 4 的專案範本內建的 ASP.NET Identity 2.1 的 IdentityUser 似乎已經沒有 Email 屬性了,請問你用的是哪一版呢?

秉程 提到...

就從 msdn https://msdn.microsoft.com/zh-tw/library/microsoft.aspnet.identity.entityframework.identityuser(v=vs.111).aspx 來看,似乎沒有看到Email 屬性。

但是只要使用 metadata 來追,其實可以發現 IdentityUser 還有一堆屬性。例如 TwoFactorEnabled,LockoutEnabled, etc.


正確來說,在2.0 版,IdentityUser 是繼承自 https://msdn.microsoft.com/en-us/library/dn613256(v=vs.108).aspx,這裡就有這些屬性了。

Share with Facebook