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

ASP.NET之FormsAuthentication表單驗證類型轉換

altumcode-dMUt0X3f59Q-unsplash
 在拜讀RM大大的 Forms AuthenticationTicket SlidingExpiration 過期問題 時

自己動手做了一下表單驗證, 結果意外發生下列問題
無法將類型 'System.Security.Principal.WindowsIdentity' 的物件轉換為類型 'System.Web.Security.FormsIdentity'。

以下片段是我用ASP.NET的表單驗證, 去建立一個 FormsAuthenticationTicket 放到cookie給用戶端使用
private void Login_Click(Object sender, EventArgs e)
{
// Create a custom FormsAuthenticationTicket containing // application specific data for the user.
string username = UserNameTextBox.Text;
string password = UserPassTextBox.Text;
bool isPersistent = false;

//若要使用Membership須設定連接的DB,會去驗證username及password是否為認可的帳密 if (Membership.ValidateUser(username, password))
{
string userData = "ApplicationSpecific data for this user.";

//建立FormsAuthenticationTicket ,表示表單驗證用它來識別已驗證的使用者的驗證票證 FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
username,
DateTime.Now,
DateTime.Now.AddMinutes(30),
isPersistent,
userData,
FormsAuthentication.FormsCookiePath);

// Encrypt the ticket. string encTicket = FormsAuthentication.Encrypt(ticket);

// Create the cookie. Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));

// Redirect back to original URL. Response.Redirect(FormsAuthentication.GetRedirectUrl(username, isPersistent));
}
else {
Msg.Text = "Login failed. Please check your user name and password and try again.";
}
}
在建立FormsAuthenticationTicket成功時,表示使用者為已驗證的狀態,

因此在Page下的Context就會被初始成功, Context是HttpContext 類別, 包含User的property

判斷使用者是否已經是登入的狀態, 可以用以下的片段
 if(User.Identity.IsAuthenticated)
{
Response.Write("您現在是已登入狀態。");
}
 
而另一種讓使用者為已驗證的狀態的方法, 可以透過 FormsAuthentication 類別中的一個 RedirectFromLoginPage 靜態方法, 如下列片段:

//strUsername可為任意字串, 一般為使用者帳號FormsAuthentication.RedirectFromLoginPage(strUsername,false); 
驗證後一樣取得Context下的任一property來使用, 可是在我載入RM大大的專案下來,

自己新增了一個Index.aspx來實作RedirectFromLoginPage 靜態方法並嘗試要取Context的東西時, 遇到了以下問題

無法將類型 'System.Security.Principal.WindowsIdentity' 的物件轉換為類型 'System.Web.Security.FormsIdentity'。
記得剛開始將專案載下來執行並沒有這個問題....於是想起因為在web.config好像有設定這麼一段
<authentication mode="Forms">  <forms loginUrl="login.aspx"         name=".rmau" 
slidingExpiration="true"
timeout="4" />
</authentication><authorization> <deny users="?"/></authorization>
FormsAuthentication 類別有提到"表單驗證的啟用方法是:將 authentication 組態項目的 mode 屬性設定為 Forms。您可以要求所有應用程式的要求都包含有效的使用者驗證票證,方法是:使用 authorization 組態項目,以拒絕任何未知使用者的要求"
言下之意是任意頁面一定要通過驗證後才可以讀取, 而最一開始的專案因為有設定loginUrl="login.aspx"導致任一頁面只要未經驗證一定會導到login.aspx
為了實驗 RedirectFromLoginPage的靜態方法, 要讓IIS啟動可以進入我自己新增的Index.aspx, 所以先拿掉了上述的web.config片段,
而雖然成功讓使用者變為已驗證的狀態, 但其中一段

FormsAuthenticationTicket ticket = ((FormsIdentity)Context.User.Identity).Ticket;
卻造成該錯誤, 原因是此時的Context.User.Identity為WindowsIdentity的型態, 強制轉成FormsIdentity而導致
 
至於驗證通過後為什麼會變成WindowsIdentity的型態, 則一定跟web.config中的設定有關係,參考authentication 項目的mode屬性, 因為其預設值為 Windows, 所以驗證後取得的Context.User.Identity則變為WindowsIdentity的型態,為了證明是拿掉mode屬性導致該錯誤, 所以這次把mode設為None, 結果轉換的時候Context.User.Identity的型態果真不一樣了!

這次變為'Unable to cast object of type 'System.Security.Principal.GenericIdentity' to type 'System.Web.Security.FormsIdentity'.的錯誤
結論: 下次遇到驗證轉換的問題一定要先確認authentication 項目設定的mode屬性
善用 JIRA Dashboard,打造自己的 Free Style
在Window IIS上跑NodeJs

相關文章

 

評論

尚無評論
已經注冊了? 這裡登入
Guest
2024/04/30, 週二

Captcha 圖像