ASP.NET安全問題--Forms驗證實戰篇
前言:通過之前的幾篇文章,相信大家對Forms驗證有了一定的瞭解,也清楚了Identity,IPrincipal,票據等概念。之前的文站一直沒有把驗證和資料庫聯絡起來,本篇就從這方面講解,用代碼來示範!而且代碼中也涉及到一些角色授權的問題,為之後的文章伏筆!
今天話題如下:
驗證流程講述
資料庫準備
代碼編寫
系列文章連結:
ASP.NET開發安全問題
ASP.NET安全問題-- 建立安全的Web應用程式
ASP.NET安全問題--ASP.NET安全架構
ASP.NET安全問題--ASP.NET安全架構--如何?.NET安全
ASP.NET安全問題--ASP.NET生命週期中的驗證以及身分識別驗證模組
ASP.NET安全問題--Forms驗證的具體介紹(上篇)
ASP.NET安全問題--Froms驗證的具體介紹(中篇)
ASP.NET安全問題--Forms驗證(後篇)--實戰篇
ASP.NET安全問題--ASP.NET中的授權問題(前篇)
驗證流程講述
我們首先假設一個情境:使用者現在已經開啟了我們的首頁Default.aspx,但是有些資源只能是登入使用者才可以看到的,那麼如果這個使用者想要查看這些資源,那麼他就要登入。而且這個使用者已經有了一個帳號。(我們本篇主要的話題是身分識別驗證,至於建立使用者賬戶是怎麼建立的,我們不關心,方法很多,如直接一個資料庫插入就行了!)
我們現在就把我們的一些流程說下:
1.使用者登入,在輸入框中輸入使用者名稱和密碼資訊
2.點擊登入按鈕後,到資料庫中查詢該使用者是否存在
3 如果存在,伺服器端代碼就建立一個身分識別驗證的票據,儲存在cookie中,然後發送到用戶端的瀏覽器
4.使用者已經有了驗證的cookie,那麼就頁面就跳轉到使用者之前請求的頁面
資料庫準備
那麼下面我們就開始詳細講述:
首先,我們我們肯定要先得建立一個資料庫,我們就取名為Login表,建立一個使用者資訊表,我們在在表中建立三個欄位UserName,UserPassword,UserRole(大家可以建立更多欄位,我這裡只是示範,大家可以擴充的). 至於表中的資料,大家自己隨便插入幾條!
代碼編寫
因為我們常常要驗證使用者,所以我們把驗證使用者的代碼寫成一個方法放在App_Code目錄下的Helpers.cs類中
代碼如下:
驗證代碼
public static bool ValidateUser(string username, string password)
{
SqlConnection con = new SqlConnection();
con.ConnectionString =
ConfigurationManager.ConnectionStrings[“MyConnectionString”].ConnectionString;
SqlCommand com = new SqlCommand();
com.Connection = con;
com.CommandText = “Select Count(*) From Users Where Username=@Username and UserPassword=@Password”;
com.Parameters.AddWithValue(“@Username”, username);
com.Parameters.AddWithValue(“@Password”, password);
con.Open();
int cnt = (int)com.ExecuteScalar();
con.Close();
return (cnt > 0);
} 然後我們就建立一個登入的頁面Login.aspx,在頁面上面放入兩個TextBox,分別用來供使用者輸入使用者名稱和密碼。 放上一個按鈕,用來登入。 回到Helpers.cs中,我再添加一個方法,來擷取使用者的角色: Code
public static string GetRoleForUser(string username )
{
//建立連結
SqlConnection con = new SqlConnection();
con.ConnectionString =
ConfigurationManager.ConnectionStrings[“MyConnectionString”].ConnectionString;
SqlCommand com = new SqlCommand();
com.Connection = con;
//執行命令
com.CommandText = “Select UseRole m Users Where Username=@Username;
com.Parameters.AddWithValue(“@Username”, username);
con.Open();
//返回結果
string userRole= (string)com.ExecuteScalar();
con.Close();
}
為了啟動Forms驗證,我們還得到web.config檔案中配置,如下: <authentication mode=”Forms”>
<forms name=”.mycookie” path=”/” loginUrl=”Login.aspx” protection=”All”
timeout=”40” />
</authentication> 並且不允許匿名使用者存取我們的網站 : <authorization>
<deny users=”?”/>
</authorization> 然後我們就開始在Login.aspx的登入按鈕下面寫代碼了:
基本思想如下: 1.驗證使用者是否存在, 2.如果存在,同時擷取使用者的角色 3.建立身分識別驗證票據和cookie,並且發送到用戶端的瀏覽器中 代碼都加了注釋,通過之前的基礎,相信大家可以對下面的代碼沒有問題。 Code
Code
protected void LoginCallback(object sender, EventArgs e)
{
if (Helpers.ValidateUser(UserName.Text, Password.Text))
{
//擷取使用者的角色
string rolenames = Helpers.GetRolesForUser(UserName.Text);
//建立身分識別驗證票據
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
UserName.Text, DateTime.Now, DateTime.Now.AddSeconds(40), false, roles);
//加密票據
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
//建立新的cookie
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName);
//把加密後的票據資訊放入cookie
cookie.Value = encryptedTicket;
//把cookie添加到響應流中
Response.Cookies.Add(cookie);
//把cookie發送到用戶端
Response.Redirect(FormsAuthentication.GetRedirectUrl(UserName.Text,false),true);
}
} 好了,現在如果我們正確的輸入使用者名稱和密碼,那麼我們的瀏覽器中就有了身分識別驗證的cookie了,現在我們的頁面就要馬上從原來的Login.aspx轉向到Default.aspx頁面了,我們現在把這個轉向的過程在頭腦中把它慢速化,因為我們要分析這個過程。 在Login.aspx轉向到Default.aspx頁面跳轉的過程中,其實我們在請求Default.aspx頁面,這個我們之前請求的過程沒有任何的區別,也是一樣要經曆ASP.NET的一些生命週期,但是這次我們的瀏覽器中已經有了身分識別驗證的cookie,ASP.NET運行時在處理,在處理Application_AuthenticateRequest事件時就要解析我們的cookie了。其實在之前我們登入之前,在這個事件代碼中也解析了cookie的,只是那時候沒有找到cookie而以。 Application_AuthenticateRequest事件的代碼中,其實就是解析cookie,然後把使用者的身份標識,並且把使用者的身份資訊儲存起來: Code
Code
Code
void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
//擷取身分識別驗證的cookie
HttpCookie cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
string encryptedTicket = cookie.Value;
//解密cookie中的票據資訊
FormsAuthenticationTicket ticket =
FormsAuthentication.Decrypt(encryptedTicket);
//擷取使用者角色資訊
string[] roles = new string[]{ticket.UserData.toString()};
//建立使用者標識
FormsIdentity identity = new FormsIdentity(ticket);
//建立使用者的主體資訊
System.Security.Principal.GenericPrincipal user =
new System.Security.Principal.GenericPrincipal(identity, roles);
app.Context.User = user;
}
}
我們看到最後一行代碼:
app.Context.User = user;,把使用者的身份以及角色資訊儲存在了User屬性中。
我們就可以在頁面中通過如下方法判斷使用者是否登入了: if (Page.User.Identity.IsAuthenticated)
{
//
} 用下面的方法判斷使用者是否屬於某個角色: if (Page.User.IsInRole("Admin")
{
//
} 其實這個我們之前講過了的Identity,IPrincipal概念有關,不清楚的可以看看之前的文章! 代碼到這裡,今天也寫完了,有關身分識別驗證的問題就要講完了,還差一個問題沒有講述:
自訂身分識別驗證以及開發自訂的HttpModule. 之後的的文章將講述
授權的問題。 謝謝大家的支援!