我之前講過一篇文章叫做簡介 ASP.NET 表單驗證 (FormsAuthentication) 的運作方式,但若要使用 Forms Authentication 來驗證使用者,又要自行指派使用者角色時那就麻煩了,通常要實做角色提供者(Role Provider)才行,是有點麻煩,我今天介紹一個更簡單、方便的自訂角色方法。
若使用 Forms Authentication 我常用的登入程式碼如下:
/// <summary>
/// 設定要存在 FormsAuthenticationTicket 中的資料,這裡用來儲存角色資訊
/// </summary>
string userData = "";
protected void Login_Button_Click(object sender, EventArgs e)
{
// 登入時清空所有 Session 資料
Session.RemoveAll();
// 登入的密碼 (以 SHA1 雜湊處理)
string strPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(txtPassword.Text, "SHA1");
if (ValidateLogin(txtAccount.Text, strPassword))
{
// 將管理者登入的 Cookie 設定成 Session Cookie
bool isPersistent = false;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
txtAccount.Text,
DateTime.Now,
DateTime.Now.AddMinutes(30),
isPersistent,
userData,
FormsAuthentication.FormsCookiePath);
// 將 FormsAuthenticationTicket 加密
string encTicket = FormsAuthentication.Encrypt(ticket);
// 將加密過的 FormsAuthenticationTicket 回應給瀏覽器儲存
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
Response.Redirect("~/Members/", true);
}
else
{
Page.ClientScript.RegisterStartupScript(Page.GetType(), "LoginFail", "alert('登入失敗,請重新登入!');", true);
}
}
/// <summary>
/// 驗證使用者是否登入成功
/// </summary>
/// <param name="strUsername">登入帳號</param>
/// <param name="strPassword">登入密碼</param>
/// <returns></returns>
private bool ValidateLogin(string strUsername, string strPassword)
{
// 驗證
// 請自行寫 Code 檢查 Username, Password 是否正確
// 授權:設定角色到 userData
userData = "gold_member,board_admin";
return true;
}
而這段程式的重點在於我將 userData
儲存在 FormsAuthenticationTicket 中,讓使用者登入資訊包括「角色」的定義,但是如果你要在程式中使用 User.IsInRole
或要在 SiteMap 檔中啟用 securityTrimmingEnabled
的話,還需要在 Global.asax
中新增 Application_AuthenticateRequest 事件,才能讓 ASP.NET 知道該使用者擁有什麼角色,如下:
void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated) {
// 先取得該使用者的 FormsIdentity
FormsIdentity id = (FormsIdentity)User.Identity;
// 再取出使用者的 FormsAuthenticationTicket
FormsAuthenticationTicket ticket = id.Ticket;
// 將儲存在 FormsAuthenticationTicket 中的角色定義取出,並轉成字串陣列
string[] roles = ticket.UserData.Split(new char[] { ',' });
// 指派角色到目前這個 HttpContext 的 User 物件去
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
}
這段程式碼我可是研究好久才整理出來的,但我覺得透過這種方式自訂「角色」感覺簡單多了,而且也不需要自己實做 Role Provider 或在資料庫中多建立一個表格。
若要啟用 SiteMap 安全限制的功能必須要在 web.config
中設定該 sitemap 定義的 securityTrimmingEnabled
屬性為 True 才行,如下:
<siteMap defaultProvider="SiteMapProvider" enabled="true">
<providers>
<add name="SiteMapProvider" description="設的 SiteMap 定義檔"
type="System.Web.XmlSiteMapProvider " siteMapFile="~/Web.sitemap"
securityTrimmingEnabled="true"/>
</providers>
</siteMap>