3.3 Intranet系統的選擇決策流程 參見圖2。
3.4 SQL Server用戶驗證 對SQL Server的客戶端進行驗證,一般說來Windows身份驗證要比SQL Server身份驗證更安全,原因主要有以下幾點: 前者負責管理用戶的憑據信息,而且用戶的憑據不會在網絡上傳輸??梢员苊庠谶B接字符串中嵌入用戶名和密碼??赏ㄟ^密碼過期時限、最小密碼長度、以及多次無效登錄后請求的帳戶鎖定等措施改進登錄安全性。這樣可以見少詞典攻擊的威脅。 但是某些特定的應用程序方案中不允許使用Windows身份驗證,例如: 數據庫客戶端和數據庫服務器由一個防火墻分隔開,從而導致無法使用Windows身份驗證。應用程序需要使用多個標識連接到一個或多個數據庫。連接到的數據庫不是SQL Server。在ASP.NET中沒有一種安全的方式以特定的Windows用戶的身份運行代碼。 在以上這些方案中,將必須使用SQL身份驗證,或是數據庫的本機身份驗證機制。
4. ASP.NET身份驗證實現 4.1 方案特性在這部分,僅提供了一種Intranet下交互式WEB應用程序的身份驗證的實現,本方案假設具有以下特性: 只有通過了身份驗證的客戶端才能訪問應用程序。數據庫相信應用程序對用戶進行了相應的身份驗證-即應用程序代表用戶對數據庫進行調用。 WEB應用程序通過使用ASP.NET進程帳戶連接到數據庫。用戶的憑據信息是根據SQL Server數據庫進行驗證的。使用窗體身份驗證模式。 在WEB應用程序中,用戶的憑據信息是根據SQL Server數據庫,采用窗體身份驗證模式,便于實現用戶個性化設計。采用應用程序代表用戶對數據庫進行調用的方式,可采用受信任子系統模型,更好地利用數據庫連接池,并且可以保證用戶不能直接訪問后端數據庫,另外可以減少后端的ACL管理工作。
4.2 安全配置步驟 4.2.1 IIS配置步驟 對Web服務的虛擬根目錄啟用匿名訪問。
主要方法是使用IIS MMC管理單元,右擊應用程序的虛擬目錄,然后單擊屬性---〉目錄安全性--〉匿名訪問和安全控制--〉編輯。
4.2.2 ASP.NET配置步驟 1. 將ASPNET帳戶(用于運行ASP.NET)的密碼重新設置為一個更安全的密碼。
這樣允許在數據庫服務器上復制一個本地帳戶(具有相同的用戶名和密碼)。為了使用Windows身份驗證連接到數據庫時,能夠使ASPNET帳戶對來自數據庫的網絡身份驗證要求進行響應,這是必須的。
具體方法是編輯位于%windr%\Microsoft.NET\Framework\v1.1.4322\CONFIG目錄下的 Machine.config文件,將<processModel>元素上的密碼屬性重新配置,將其默認值<!-UserName= "machine" password="AutoGenerate" -->改為<!-UserName="machine" password="NewPassword" -->。
2. 配置ASP.NET,使用窗體身份驗證。
編輯位于WEB服務的虛擬根目錄下的Web.config文件,將<authentication>元素設置為:
<authentication mode="Forms" >
<forms name="MyAppFormAuth" loginUrl="login.aspx" protection="All" timeout="20" path="/">
</forms>
</authentication>
4.2.3 配置SQL Server 1. 在SQL Server數據庫上創建一個和ASP.NET進程帳戶匹配的Windows帳戶。
用戶名和密碼必須和ASP.NET應用程序帳號匹配。
2. 配置SQL Server,使其使用Windows身份驗證。
3. 為自定義的ASP.NET應用程序帳戶創建一個SQL Server登錄,授予對SQL Server的訪問權。
4. 創建一個新的數據庫用戶,并將登錄名映射為數據庫用戶。
5. 創建一個用戶定義的新數據庫角色,并將數據庫用戶添加到該角色。
6. 為數據庫角色確定數據庫權限。
4.3 程序代碼 4.3.1 身份驗證事件序列 當未通過身份驗證的用戶試圖放一個受保護的文件或資源被拒絕時,觸發的事件序列如圖3所示。
4.3.2 代碼實現步驟 1. 建一個WEB登錄窗體并驗證用戶提供的憑據信息
根據SQL Server數據庫來驗證憑據信息。
2. 從數據庫里獲取角色列表
3. 創建窗體身份驗證票證
在票證中保存所獲取的角色信息。示例代碼如下:
private void btnLogin_Click(object sender, System.EventArgs e)
{
//根據SQL Server數據庫進行驗證(具體實現略)。
bool isAuthenticated = IsAuthenticated( txtUserName.Text, txtPassword.Text );
if (isAuthenticated == true )
{
//獲取用戶的角色
string roles = GetRoles( txtUserName.Text, txtPassword.Text ); // 創建身份驗證票證
FormsAuthenticationTicket authTicket = new
FormsAuthenticationTicket(1, // version
txtUserName.Text, // user name
DateTime.Now, // creation
DateTime.Now.AddMinutes(60),// Expiration
false, // Persistent
roles ); // User data
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
// 創建Cookie
HttpCookie authCookie =
new HttpCookie(FormsAuthentication.FormsCookieName,
encryptedTicket);
Response.Cookies.Add(authCookie);
// 將用戶重定向到最初請求頁面。
Response.Redirect( FormsAuthentication.GetRedirectUrl(
txtUserName.Text,
false ));
}
}
4. 創建IPrincipal對象 可在Application_AuthenticateRequest事件中創建一個IPrincipal對象,一般使用GenericPrincipal類。
5. 將IPrincipal對象置于當前的HTTP上下文
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
// 提去窗體身份驗證cookie
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if(null == authCookie)
{
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch(Exception ex)
{
return;
}
if (null == authTicket)
{
return;
}
//提取角色
string[] roles = authTicket.UserData.Split(new char[]{'|'});
// 創建Identity object
FormsIdentity id = new FormsIdentity( authTicket );
GenericPrincipal principal = new GenericPrincipal(id, roles);
Context.User = principal;
}
具體的代碼讀者可以自行補充完成。
5. 后記與授權與安全通訊有關的內容將另外論述。 ---------------------- 服務器安全討論區
http://www.safe263.cn