.Net Framework 內建有三種不同的驗證系統可使用(authentication) ,第一是利用 Windows 的安全保護,第二是微軟的 .Net Passport 驗證,第三則是大家熟悉的表單驗證• 每一種驗證方式都有不同的用處、能力及安全注意事項• 此篇文章將只會向大家介紹表單驗證... 因為這是目前最常見,事實上也是最方便的驗證方式• (更進階的應用將會在下一次講解)
簡介一般表單驗證安全
表單驗證系統,很顯然的它是一個完全依賴網頁程式去創造/執行使用者驗證、權限分配、授權等其他安全動作的系統• 以一個普遍的表單驗證程式來講,網站會員基本上的操作範圍都會限制在網頁上,並不在整個作業系統上•而且這種驗證方法也可以和 Windows 用不同的使用者帳號... 也就是說,同樣也是網站會員的作業系統使用者都有機會使用不同的帳號、權限及密碼• 所以就算網頁程式不幸遭到入侵或密碼外洩的話,也不至於會對作業系統構成威脅•
其實任何一個驗證系統最重要的安全關卡都在於使用者身份防護上(user identity),而再分類下來的話,這個安全關卡基本上總共有三種安全性原則,分別為 驗證 (Authentication)、受權 (Authorization)、和檢查 (validation) • 如果您要編寫一個有驗證系統的網站,建議您事先就仔細規劃和分配好這方面的安全設計! 因為一個缺少有規劃的會員網站,這方面的保護疏忽就可能比較高... 網站自然就會更不安全• 而這種漏洞(尤其是檢查缺失),也是所有網站攻擊者所愛找的•
另外,由於這種程式儲存的資料有些是不可外流的,所以保護敏感資料也是寫驗證系統時所必須要考量的範圍• 而為了要設計一個更安全的網站,除了要想如何去 防治 以外,我們也必須要考慮到自己不幸被入侵,資料被偷到的問題... 要減輕這個安全問題的話,我們可以使用資料編碼去保護資料•其實資料編碼有三種不一樣的方式,它們分別為 Encryption、Encoding、和Hashing• Encryption 必須要有它的 secret-key 去編碼/解碼,Encoding 的話則使用public-key (像是algorithm),但 hash 出來的資料卻沒辦法解碼,因為它加密的原則就是就是基於未加密前的資料 (你也可以說,hash 根本沒有 key)• 另外值得注意的是,在您加密/解密資料的同時,程式必須要花時間和空間去算和儲存,所以我們的優先考量都應該是先將極重要的資料保護好(像是密碼) 為第一,使用者其他的資料則可以擺其次(或不用加密以提升速度)•至於要用什麼方式去加密資料,這應該是設計者自己的選擇• (關於如何在 ASP.Net 使用MD5 hash,您可以在之前我寫過的舊文章找到)
我在這邊差不多已經簡單說明了幾個重要的安全部分,雖然表單驗證有它自己另外所要注意到的安全,我們也要注意一般網頁程式可能會面臨到的攻擊問題• 駭客除了會嘗試入侵您的網頁程式跟主機外,他們也可以把箭頭直接指向會員的個人電腦... 在這裡,以一個設計者或網管的角度來看,事實上客戶自己的電腦是管不到的! 我們也許無法讓會員的電腦去必免駭客的木馬、病毒等其他攻擊... 但我們卻可以確保客戶瀏覽器與主機之前有一個安全的傳輸通道可用,至少這主要可以必免攻擊者的封包攔截問題 (就算資料被攔到了,但卻無法讀取)• 要用這個安全連線的話,Secure Socket Layer (SSL) 會是我們的選擇• 但在這邊我就不再繼續解釋 SSL 了,因為這又會把話題扯更遠了• 如果您想要知道更多關於這方面的資訊,本文的最後會提供幾個連結讓大家參考 :-)
關於 ASP.Net 表單驗證
ASP.Net 的 forms authentication 就跟一般其他的驗證登入程式一樣,要先輸入自己密碼,然後判斷,處理,再受權身份,最後轉頁• 不過 ASP.Net 卻是使用 cookie 去儲存使用者登入資料的• 也許您會認為這很不安全,設計者反而會自動完全依賴 cookie (在這邊,cookie 是使用者登入網頁時所需的 "ticket")• 但在預設,ASP.Net forms authentication 卻會對這一個 cookie 資料做三重 DES (Encryption) 或 DES 加密,而且也還會在建立cookie 時在緩衝區中串連驗證金鑰與 Cookie 資料,並計算成MAC (Machine Authentication Check) 然後放到 cookie 裡去,這樣就可以隨時檢查資料的內容是否有被更改•
另外,ASP.Net 拒絕使用者登入的方式是,直接 Deny 所有以匿名登入的來訪者• 您可以不必另外譔寫任何程式碼,因為這個動作只要在 Web.Config 檔案裡設定就行了•
使用Formsauthentication class
Formsauthentication 是 .Net Framework 裡 System.Web.Security namespace 的其中一個 class,這個 class 的主要工作在於提供控制表單驗證許可(ticket)的功能•
範本程式
以下我將會利用 Code Behind 的編寫方式寫出幾個範例參考,如果您對哪一個 Class 或 NameSpace 不熟悉的,本文章最後有提供幾個對 coding 很有幫助的參考資料•
程式範本參考: web.config
Purpose: Web application configuration
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation defaultLanguage="vb" debug="true" />
<authentication mode="Forms">
<forms name="aspxauth" loginUrl="signin.aspx" protection="All" timeout="60" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<trace enabled="false" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true" />
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20"
/>
<globalization requestEncoding="utf-8" responseEncoding="utf-8" />
</system.web>
</configuration>
程式範本參考: signin.aspx.vb
Purpose: 處理使用者登入
Imports System.Data.OleDb
Imports System.Web.Security
Public Class signin
Inherits System.Web.UI.Page
Private conn As OleDbConnection
#Region " Web Form Designer Generated Code "
'' Web Form Designer Generated Code 就不另外列出了
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim verify_auth_cookie As HttpCookie = Request.Cookies(FormsAuthentication.FormsCookieName)
If Not verify_auth_cookie Is Nothing Then
Response.Redirect("default.aspx")
End If
conn = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("user_db.mdb") & ";Jet OLEDB:Database Password=test")
conn.Open()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim dbreader As OleDbDataReader
Dim getdata(1) As String
getdata(0) = username.Text.Trim
getdata(1) = pwd.Text.Trim
Dim dbcmd As New OleDbCommand("Select * from user_database where user_account = @username and user_pwd = @userpwd", conn)
dbcmd.Parameters.Add(New OleDbParameter("@username", getdata(0)))
dbcmd.Parameters.Add(New OleDbParameter("@userpwd", getdata(1)))
dbreader = dbcmd.ExecuteReader()
If dbreader.Read = True Then
Dim form_ticket As New FormsAuthenticationTicket(1, getdata(0), Now(), Now.AddDays(365), autosignin.Checked, dbreader("role"))
Dim user_ticket As String = FormsAuthentication.Encrypt(form_ticket)
Response.Cookies(FormsAuthentication.FormsCookieName).Value = user_ticket
Response.Redirect("default.aspx")
Else
errmsg.Text = "Incorrect username or password<br>"
End If
End Sub
Private Sub Page_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Unload
conn.Close()
End Sub
End Class
程式範本參考: default.aspx.vb
Purpose: 使用者登入後所應該要導入的預設頁
Imports System.Web.Security
Public Class _default
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'Web Form Designer Generated Code 就不另外列出了
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim userid As FormsIdentity = CType(User.Identity, FormsIdentity)
Dim user_ticket As FormsAuthenticationTicket = userid.Ticket
username.Text = user_ticket.Name.Trim
userdata.Text = user_ticket.UserData.Trim
isuserauthenticated.Text = userid.IsAuthenticated
isssl.Text = FormsAuthentication.RequireSSL
isautosignin.Text = user_ticket.IsPersistent
signindate.Text = user_ticket.IssueDate.ToString()
End Sub
Private Sub sign_out_button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles sign_out_button.Click
FormsAuthentication.SignOut()
Response.Redirect("signin.aspx")
End Sub
End Class
參考連結
Secure Socket Layer (SSL) 解釋:
http://www.moneydj.com/z/glossary/glexp_405.asp.htm
SSL Certificates:
http://www.verisign.com/
如何在 MS IIS 使用 SSL連線:
http://support.microsoft.com/default.aspx?kbid=324069
ASP.Net MD5 hash 資料密碼保護做法:
http://tek.fetag.org:8080/read_article.aspx?id=9
FormsAuthentication class 的 member 參考:
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemwebsecurityformsauthenticationmemberstopic.asp?frame=true
FormsAuthenticationTicket class 的 member 參考:
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemwebsecurityformsauthenticationticketmemberstopic.asp?frame=true