ASP.NET實現匿名存取控制
通過學習我掌握了兩種控制方法,實現了對於網站的匿名存取控制,一個是通過IIS實現,另一個是通過ASP.NET實現。個人感覺兩種基本上可以實現的功能沒有什麼差別,不過通過ASP.NET實現的更易於管理和維護。
對於通過IIS的實現都比較清楚,可以對檔案夾或單個檔案(頁面)設定存取權限,IIS提供了“目錄安全性”和“檔案安全性”的設定方法。並可以通過直接設定不同訪問人的許可權。其中就提供了匿名訪問的控制方法,這裡不再細說。
ASP.NET控制方法:
首先介紹例子實現的效果,一個網站登陸以後可以將使用者資訊儲存在一個cookie中,並標識使用者是通過身分識別驗證的,在訪問其他頁面的時候直接對使用者的身份是否通過驗證進行判斷,如果通過即可繼續訪問頁面,如果是一個未通過驗證的匿名訪問使用者(即未登入使用者)則將跳轉到登陸頁面提示使用者登入。設定其中一個使用者註冊頁面為可以匿名訪問,因為商務邏輯上只有允許註冊才能登陸。
在登陸頁面還是先對使用者的使用者名稱和密碼進行驗證,至於使用與資料庫比對的方法還是到AD中驗證等都可以,然後通過以下的方法將目前使用者在cookie中標識為通過驗證的使用者,並跳轉到使用者跳轉到登陸頁之前請求的頁面。
FormsAuthentication.RedirectFromLoginPage(userName,createPersistentCookie);
FormsAuthentication.RedirectFromLoginPage(UserEmail.Value, PersistCookie.Checked);
在使用者直接請求的頁面上我們使用如下的方法來驗證使用者。
Context.User.Identity.IsAuthenticated
Context:擷取與該頁關聯的 System.Web.HttpContext 對象
User:為當前 HTTP 要求擷取或設定安全資訊
Identity:擷取目前使用者的標識
IsAuthenticated:擷取一個bool值,該值指示是否驗證了使用者
然後我們在Web.config中進行安全設定。
<authentication mode="Forms">
<forms loginUrl="Login.aspx"></forms>
</authentication>
"Forms" 您為使用者提供一個輸入憑據的自訂表單(Web 頁),然後在您的應用程式中驗證他們的身份。使用者憑證標記儲存在 Cookie 中。
<authorization>
<deny users="?" />
</authorization>
deny表示禁止,users="?"表示匿名使用者
<location path="NewUser.aspx">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
表示新使用者註冊頁面NewUser.aspx,可以允許任何人訪問。
這樣就實現了對於匿名使用者的存取控制。
對於機密目錄,我們可以參照以下的說明:
我們設定機密目錄(也就是"安全目錄",特定的使用者如管理員才有許可權訪問的目錄)。首先看看你的Web應用程式根目錄下是否有 Web.config 這個檔案,如果沒有就建立一個。你也可以在你的子目錄中建立 Web.config 檔案,當然,這個 Web.config 檔案是有限制的(一些參數它不可以設定)。要實現安全認證,在 Web應用程式根目錄下的 Web.config 檔案中找到 <system.web> 節點下的
程式碼
<authentication mode="Windows" />,把它修改為
<authentication mode="Forms">
<forms name="AMUHOUSE.ASPXAUTH"
loginUrl="Login.aspx"
protection="All"
path="./" />
</authentication>
<authorization>
<allow users="*"/>
</authorization>
上面的 name="AMUHOUSE.ASPXAUTH" 中,AMUHOUSE.ASPXAUTH 這個名稱是任意的。要控制使用者或者使用者組的許可權,我們可以有兩種方法,一是配置在應用程式根目錄下的 Web.config 檔案,二是在機密目錄下建立一個獨立的 Web.config 檔案。(後者也許會比較好。)如果是前者,這個Web.config 就應該包含有下面的內容(或者類似的內容):
程式碼
<configuration>
<system.web>
<authentication mode="Forms">
<forms name=" AMUHOUSE.ASPXAUTH"
loginUrl="login.aspx"
protection="All"
path="/"/>
</authentication>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
<location path="./Admin">
<system.web>
<authorization>
<!-- 注意!下面幾行的順序和大小寫是非常重要的! -->
<allow roles="Administrator"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<location path="./User">
<system.web>
<authorization>
<!-- 注意!下面幾行的順序和大小寫是非常重要的! -->
<allow roles="User"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
</configuration>
為了使Web應用程式的目錄之前不互相依賴,可以比較方便的改名或者移動,可以選擇在每一個安全子目錄下配置單獨的 Web.config 檔案。它只需要配置 <authorization/>節點,如下:
程式碼
<configuration>
<system.web>
<authorization>
<!-- 注意!下面幾行的順序和大小寫是非常重要的! -->
<allow roles="Administrator"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
需要再次提醒的是,上面的角色 roles 是大小寫敏感的,為了方便,你也可以把上面修改為:
<allow roles="Administrator,administrator" />
如果你想允許或者禁止多個角色對這個目錄的訪問,可以用逗號隔開,如:
<allow roles="Administrator,Member,User" />
<deny users="*" />
至此,我們已經為網站配置了基於角色的安全認證機制了。你可以先編譯你的程式,然後嘗試訪問一個機密目錄,例如 http://localhost/RolebasedAuth/Admin ,這時候你就會被轉向到使用者登入頁面。如果你登入成功,並且你的角色對這個目錄有存取權限,你就重新回到這個目錄下。可能會有使用者(或入侵者)企圖進入機密目錄,我們可以使用一個 Session 來儲存使用者登入的次數,超過一定次數就不讓使用者登入,並且顯示"系統拒絕了你的登入請求!"。
下面,我們討論如何根據使用者角色讓Web控制項顯示不同內容。
有時候根據使用者的角色來顯示內容比較好,因為你可能不想為那麼多不同的角色(使用者群組)製作一大堆有許多重複內容的頁面。這樣的網站,各種使用者帳戶可以並存,付費的使用者帳戶能夠訪問附加的付費內容。另一個例子是一個頁面將顯示一個 "進入後台管理" 按鈕連結到後台管理頁面如果目前使用者是 "Administrator"(進階管理員)角色。我們現在就實現這個頁面。
我們上面用到的 GenericPrincipal 類實現了 IPincipal 介面,這個介面有一個方法名叫做 IsInRole(),它的參數是一個字串,這個字串就是要驗證的使用者角色。如果我們要顯示內容給角色是 "Administrator"的已登入使用者,我們可以在 Page_Load 中添加下面代碼:
程式碼
if (User.IsInRole("Administrator"))
AdminLink.Visible = true;
整個的頁面代碼如下(為了簡便,把後台代碼也寫在aspx頁面):
程式碼
<html>
<head>
<title>歡迎您!</title>
<script runat="server">
protected void Page_Load(Object sender, EventArgs e)
{
if (User.IsInRole("Administrator"))
AdminLink.Visible = true;
else
AdminLink.Visible = false;
}
</script>
</head>
<body>
<h2>歡迎!</h2>
<p>歡迎來到阿木小屋 http://amuhouse.com/ ^_^</p>
<asp:HyperLink id="AdminLink" runat="server"
Text="管理首頁" NavigateUrl="./Admin"/>
</body>
</html>
這樣,連結到 Admin 目錄的HyperLink 控制項只會顯示給角色是 Administrator 的使用者。你也可以根據為未登入使用者提供一個連結到登入頁面,如:
程式碼
protected void Page_Load(object sender, System.EventArgs e)
{
if (User.IsInRole("Administrator"))
{
AdminLink.Text = "管理員請進";
AdminLink.NavigateUrl="./Admin";
}
else if(User.IsInRole("User"))
{
AdminLink.Text = "註冊使用者請進";
AdminLink.NavigateUrl="./User";
}
else
{
AdminLink.Text = "請登入";
AdminLink.NavigateUrl="Login.aspx?ReturnUrl=" + Request.Path;
}
}
這裡,我們通過設定叫做ReturnUrl的 QueryString 變數,可以使使用者登入成功後返回到當前的這個頁面.
下面是一個簡單例子:
Default.aspx:
<%@ Import Namespace="System.Web.Security " %>
<html>
<script language="C#" runat=server>
void Page_Load(Object Src, EventArgs E ) {
Welcome.Text = "Hello, " + User.Identity.Name;
}
void Signout_Click(Object sender, EventArgs E) {
FormsAuthentication.SignOut();
Response.Redirect("login.aspx");
}
</script>
<body>
<h3><font face="宋體">使用 Cookie 身分識別驗證</font></h3>
<form runat=server>
<h3><asp:label id="Welcome" runat=server/></h3>
<asp:button text="登出" OnClick="Signout_Click" runat=server/>
</form>
</body>
</html>
login.aspx:
<%@ Import Namespace="System.Web.Security " %>
<html>
<script language="C#" runat=server>
void Login_Click(Object sender, EventArgs E) {
if (((UserEmail.Value == "jdoe@somewhere.com") && (UserPass.Value == "password")) || ((UserEmail.Value == "mary@somewhere.com") && (UserPass.Value == "password"))) {
FormsAuthentication.RedirectFromLoginPage(UserEmail.Value, PersistCookie.Checked);
}
else {
Msg.Text = "憑據無效:請再試一次";
}
}
</script>
<body>
<form runat=server>
<h3><font face="宋體">登入頁</font></h3>
<table>
<tr>
<td>電子郵件:</td>
<td><input id="UserEmail" type="text" runat=server/></td>
<td><ASP:RequiredFieldValidator ControlToValidate="UserEmail" Display="Static" ErrorMessage="*" runat=server/></td>
</tr>
<tr>
<td>密碼:</td>
<td><input id="UserPass" type=password runat=server/></td>
<td><ASP:RequiredFieldValidator ControlToValidate="UserPass" Display="Static" ErrorMessage="*" runat=server/></td>
</tr>
<tr>
<td>持久的 Cookie:</td>
<td><ASP:CheckBox id=PersistCookie runat="server" /> </td>
<td></td>
</tr>
</table>
<asp:button text="登入" OnClick="Login_Click" runat=server/>
<p>
<asp:Label id="Msg" ForeColor="red" Font-Name="Verdana" Font-Size="10" runat=server />
</form>
</body>
</html>
web.config:
<configuration>
<system.web>
<authentication mode="Forms">
<forms name=".ASPXUSERDEMO" loginUrl="login.aspx" protection="All" timeout="60" />
</authentication>
<authorization>
<deny users="jdoe@somewhere.com" />
<deny users="?" />
</authorization>
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" />
</system.web>
</configuration>