原文地址: https://blog.csdn.net/chadcao/article/details/7859394 ASP.NET的安全認證,共有“Windows”、“Form”、“Passport”、“None”四種驗證模式。下麵來說說From認證,內容分三部分: 第一部分—— 怎樣實現Fro ...
原文地址: https://blog.csdn.net/chadcao/article/details/7859394
ASP.NET的安全認證,共有“Windows”、“Form”、“Passport”、“None”四種驗證模式。下麵來說說From認證,內容分三部分:
第一部分—— 怎樣實現From 認證;
第二部分—— Form 認證的實戰運用;
第三部分—— 實現單點登錄(Single Sign On)
第一部分如何運用 Form表單認證
一、新建一個測試項目
為了更好說明,有必要新建一個測試項目(暫且為“FormTest”),包含三張頁(Default.aspx、Login.aspx、UserInfo.aspx)。
二、修改 Web.config
1、 雙擊項目中的Web.config
2、 找到下列文字<authenticationmode="Windows"/> 把它改成:
<authenticationmode="Forms">
<formsloginUrl="Login.aspx"name=".ASPXAUTH"></forms>
</authentication>
3、 找到<authorization><allowusers="*"/></authorization>換成
<authorization><denyusers="?"></deny></authorization>
<authenticationmode="Forms"> <forms loginUrl="Login.aspx" name=".APSX"></forms> <denyusers="?"></deny> </authentication>
三、編寫 .cs代碼——登錄與退出
1、 登錄代碼:
code1:
private void Btn_Login_Click(object sender, System.EventArgs e) { if(this.Txt_UserName.Text=="Admin" && this.Txt_Password.Text=="123456") { System.Web.Security.FormsAuthentication.RedirectFromLoginPage(this.Txt_UserName.Text,false); } }
code2:
privatevoid Btn_Login_Click(object sender, System.EventArgs e) { if(this.Txt_UserName.Text=="Admin" && this.Txt_Password.Text=="123456") { System.Web.Security.FormsAuthentication.SetAuthCookie(this.Txt_UserName.Text,false); Response.Redirect("Default.aspx"); } }
以上兩種都可發放驗證後的Cookie ,即通過驗證。
區別:
code1:指驗證後返回請求頁面,俗稱“從哪來就打哪去”。比如:用戶沒登錄前直接在 IE地址欄輸入http://localhost/FormTest/UserInfo.aspx ,那麼該用戶將看到的是 Login.aspx?ReturnUrl=UserInfo.aspx,輸入用戶名與密碼登錄成功後,系統將根據“ReturnUrl”的值,返回相應的頁面。
code2:則是分兩步走:通過驗證後就直接發放 Cookie ,跳轉頁面將由程式員自行指定,此方法多用於Default.aspx 使用框架結構的系統。
2、 退出代碼:
privatevoid Btn_LogOut_Click(object sender, System.EventArgs e) { System.Web.Security.FormsAuthentication.SignOut(); }
四、如何判斷驗證與否及獲取驗證後的用戶信息
有的時候,在同一張頁面需要判斷用戶是否已經登錄,然後再呈現不同的佈局。有人喜歡用Session 來判斷,我不反對此類做法,在此我只是想告訴大家還有一種方法,且看下麵代碼:
if(User.Identity.IsAuthenticated) { //你已通過驗證,do something... }
User.Identity還有兩個屬性AuthenticationType(驗證類型)與Name(用戶名稱),大家要註意的是 Name 屬性,此處的User.Identity.Name將得到,驗證通過(RedirectFromLoginPage或SetAuthCookie)時,我們帶入的第一個參數this.Txt_UserName.Text。這個參數很重要,關係到種種情況
第二部分 Form認證的實戰運用
一、Web.config 的作用範圍
新建項目時, VS.Net會在項目根目錄建立一個內容固定的 Web.config。除了在項目根目錄,你還可以在任一目錄下建立 Web.config,條件就是應用程式級別的節點只能在根目錄的 Web.config中出現。
關於 Web.config設置的作用範圍,記住以下兩點:
1、 Web.config的設置將作用於所在目錄的所有文件及其子目錄子文件(繼承:子隨父姓)
2、 子目錄下的 Web.config設置將覆蓋由父目錄繼承下來的設置(覆蓋:縣官不如現管)
二、學會拒絕與巧用允許
註冊頁 面(Register.aspx)與審核頁面(Auditing.aspx),當訪問Register.aspx時,卻回到了Login.aspx?ReturnUrl=Register.aspx。這是一個問題。
1、 新建一個目錄 Public,用於存放一些公用的文件,如萬年曆、腳本呀……
2、 在“解決方案資源管理器”中右擊點擊目錄 Public,新增一個 Web.config
3、 把上述 Web.config的內容統統刪除,僅留以下即可:
<?xmlversion="1.0"encoding="utf-8"?> <configuration> <system.web> <authorization><allow users="*"/></authorization> </system.web> </configuration>
根據“覆蓋”原則,我們知道上述 Web.config將替代根目錄 Web.config中的<authorization>節點設置,即:
<allowusers="*"/>替換 <deny users="?"></deny>
註解:“allow”允許的意思;“*”表示所有用戶;
“deny”拒絕的意思;“?”表示匿名用戶;
因此,處於 Public目錄下的文件,允許所有人瀏覽,包括未驗證的用戶。把 Register.aspx 放到這裡,在沒有登錄的時候也可以訪問了。
審核頁面(Auditing.aspx),審核許可權一般都在管理員或主管手裡,並不想讓其他人瀏覽此頁面。
新建一個管理員的目錄 ManageSys ,在此目錄下再新增一個 Web.config。內容如下:
<?xmlversion="1.0"encoding="utf-8"?> <configuration> <system.web> <authorization> <allow users="Admin"/> <deny users="*"/> </authorization> </system.web> </configuration>
現在的問題就是怎麼才能知道誰是“Admin”呢,在第一部分說到:
System.Web.Security.FormsAuthentication.SetAuthCookie(this.Txt_UserName.Text,false); //通過驗證,發放Cookie
this.Txt_UserName.Text是allow與deny的依據,上文的意思為當this.Txt_UserName.Text==“Admin”賬號時可以訪問ManageSys目錄下的文件。
例子:此項目有兩部門使用,其中每個部門分別都有些特定的頁面僅供本部門用戶瀏覽使用,請問該如何使用 Web.config達到效果?
只需要在驗證用戶名與密碼後,取得該用戶的部門名稱或部門代碼,把它作為判斷的依據就行了。
Web.config中的 <location>節點的path屬性可以是一張具體頁面的相對 URL路徑,如下:<location path ="ManageSys/Auditing.aspx">
三、分散與集中
到目前為此,我們的測試項目“FormTest”已經擁有兩個目錄三個 Web.config,伴隨用戶需求的多樣化,Web.config也會越來越多,比如常用的文件上傳功能等等。眾多的 Web.config分佈在不同的目錄裡面,維護起來肯定比較煩人。能不能集中起來管理呢,怎樣做?
要想集中管理,不得不用到<location>節點與 path 屬性。在本項目中,我們將目錄 Public與 ManageSys下的設置放在根目錄下的 Web.config裡面,如下:
<?xmlversion="1.0"encoding="utf-8"?> <configuration> <location path ="Public"> <system.web> <authorization><allowusers="*"/></authorization> </system.web> </location> <location path ="ManageSys"> <system.web> <authorization><allowusers="Admin"/><denyusers="*"/></authorization> </system.web> </location> <system.web> <!-- 這裡放置原來根目錄 Web.config 的內容,就不列出來了 --> </system.web> </configuration>
註意點:
1、 <location>節點的位置是在 <configuration>的一個子節點,它與原有的 <system.web>屬於併列關係
2、 <location>節點只需要放入對應子目錄 Web.config中的 <system.web>的節點內容
四、額外的保護
認證的目的就是為了防止他人非法瀏覽頁面,或未經許可使用某些功能。當然,世上沒有絕對的安全,如今 MD5加密都被我們國人給破解了,就是最好的例證。
細心的人可能早就發現 ASP.NET的安全認證只針對 .aspx、.ascx…… 等 ASP.NET 文件起作用,而對普通頁面與文件卻“視而不見”,如 .htm、.js、.jpg等。通過以下步驟你就可以保護你想保護的文件類型。
1、 打開 Internet信息服務(IIS)管理器→ 右擊本項目虛擬目錄 → 屬性,如下圖
2、 點擊按鈕“配置”,出現如下對話框:
3、 雙擊 .aspx的應用程式擴展 → 查看對話框內容,如下圖:
4、 複製“可執行文件”的全路徑名稱後→ 點擊“取消”返回上一層對話框 → 點擊按鈕“添加”
5、 粘貼剛纔複製的內容(我的系統裝在 D盤,所以內容為D:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll) → 填寫尾碼名為 .htm→ 填寫動作限製為“GET,HEAD,POST,DEBUG”
6、 最後點擊“確定”→ 往項目中添加 HtmlPage1.htm →在 IE 瀏覽器的地址欄直接輸入http://localhost/FormTest/HtmlPage1.htm→ 觀看測試效果
第三部分實現單點登錄(Single Sign On)
一、Machine.config
Machine.config ,在C:\WINDOWS【或WINNT 】\Microsoft.NET\Framework\v1.1.4322【或v1.0.3705 】\CONFIG,控制著 .NET Framework的本機配置。
Machine.config 與 Web.config是父子關係,同樣適用於繼承與覆蓋。
1、 Machine.config中的設置將作用於運行在本機的所有站點及其虛擬目錄,遇到子目錄將一直繼承下去。
2、 Web.config中的設置將覆蓋由 Machine.config中繼承下來的對應的節點設置
Machine.config中的 <system.web>節點所有內容都能出現在項目根目錄下的 Web.config中,也就是說能在 Web.config中的內容已經在 Machine.config中一一列出。
其中<system.web>節點下的 <pages> 還能出現在頁面上,如: HTML視圖下,在WebForm1.aspx的第一行加上<pages>的節點內容validateRequest="false"。如:
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="FromTest.WebForm1" validateRequest="false" %>
二、單點登錄(Single Sign On)的前提條件
何為單點登錄(Single Sign On)?從字面理解就是在一個地方登錄,通常運用於 ASP.NET分散式環境中(跨單個伺服器上的多個應用程式或在網路場中)的 Forms身份驗證。比如登錄QQ空間之後,就不需要在QQ音樂里登錄了,臺灣香港又把Single Sign On稱為“單一登入”。
要想實現此功能,首要條件是需要一組用於加密與驗證加密的密鑰。它們位於 Machine.config中,修改 <system.web>節點下的 <machineKey>節點屬性,如下:
<machineKeyfirstKey="172"copyrightKey="Cityhunter172" validationKey="AD117F2F286CDCB15A9D1D4535E16DB0248026939**AUTHOR**CITYHUNTER172****WEBSITE**172*MEIBU*COM****MAILTO**CITYHUNTER172@126*COM*****F2F286CDCB15A9D1D4535E16DB0248026939"secondKey="meibu"decryptionKey="3C89AE62AD117F2F286CDCB15A9D1D4535E16DB0248026939"validation="SHA1" thirdKey="com" />
1、 validationKey為用於驗證加密數據的密鑰。最小長度為 40個字元(20位元組),最大長度為 128個字元(64位元組)。
2、 decryptionKey為用於加密數據的密鑰。長度只有 16個字元(8位元組)與 48個字元(24位元組)兩種。
3、 validation為用數據驗證使用的加密類型。擁有“SHA1”“MD5”“3DES”三種方法
4、 大伙參照上述<machineKey>試著在WebForm1.aspx運行下列語句:
this.TextBox2.Text ="ht"+"tp"+"://"+firstKey+"."+secondKey+"."+thirdKey
大家在修改之前請先備份一下 Machine.config,到時要是出錯可別怪我沒提醒你。以上密鑰並不是胡亂得來的,接下來向大家介紹生成密鑰的方法。
我們把上面中提到的WebForm1.aspx 拖入本項目的 Public 目錄下,再往頁面上拖入一個TextMode=MultiLine的TextBox3與一個 Button編寫按鈕事件與函數:
private void Button1_Click(object sender, System.EventArgs e) { string decStr = this.CreateKeyString(int.Parse(this.TextBox1.Text)); string valStr = this.CreateKeyString(int.Parse(this.TextBox2.Text)); this.TextBox3.Text=string.Format("<machineKey validationKey=\"{0}\" decryptionKey=\"{1}\" validation=\"SHA1\"/>",valStr,decStr); } /// <summary> /// 生成加密型強隨機 Key 值 /// </summary> /// <param name="i">Key的有效長度: /// decryptionKey 的有效值為 8 或 24; /// validationKay 的有效值為 20 至 64 /// </param> private string CreateKeyString(int i) { System.Security.Cryptography.RNGCryptoServiceProvider rng =newSystem.Security.Cryptography.RNGCryptoServiceProvider(); //加密隨機數生成器 byte[] bt = new byte[i]; rng.GetBytes(bt);//用加密型強隨機值序列填充位元組數組 System.Text.StringBuilder str =new System.Text.StringBuilder(); for(int j= 0;j<i;j++) { str.Append(string.Format("{0:X2}",bt[j]));//轉換成大寫的十六進位文本 } return str.ToString(); }
每次點擊按鈕生成密鑰都不同,大家不妨多點幾次。切換至 HTML視圖,到WebForm1.aspx第一行把validateRequest="false"去掉,然後再多點幾次 Button1試試,看看會有什麼效果。
三、單點登錄(Single Sign On)的站點示例
將上述 TextBox3產生的文本,覆蓋Machine.config中的,現在你的機器已經具備了單點登錄的條件。大伙可以再新建一個項目FormTest2 ,從 FormTest2 登錄後直接輸入 FormTest中的Default.aspx的網址(http://localhost/FormTest/ Default.aspx),反之亦可。
下麵結合實例講解:環勝數位網站、許可權管理系統、IT內部管理網,我把這三個不相干的項目做成了單點登錄的模式,加上整合站點的主頁面,共有四個地方可以進行登錄。因為用戶 Table的結構不同,因此只有一個入口能在進入後,在跳轉站點時不會出錯,那就是在整合頁面登錄。以下meibu.com為舉例的功能變數名稱。
現在我想把環勝數位這個站點單獨脫離出來,而剩下的兩個站點繼續實現單點登錄,該怎麼做呢?或者是我的ASP.NET的空間是租的,服務商肯定不可能讓我修改 Machine.config ,根據上述 Machine.config與 Web.config的關係,我們可以把 <machineKey>節點放入項目根目錄下Web.config的<system.web>節點。如下:
1、 許可權管理系統項目的 Web.config用於 Form認證的設置
<machineKeyvalidationKey="AD117F2F286CDCB15A9D1D4535E16DB0248026939**AUTHOR**CITYHUNTER172****WEBSITE**172*MEIBU*COM****MAILTO**CITYHUNTER172@126*COM*****F2F286CDCB15A9D1D4535E16DB0248026939"decryptionKey="3C89AE62AD117F2F286CDCB15A9D1D4535E16DB0248026939"validation="SHA1" />
<authenticationmode="Forms">
<formsloginUrl="Login.aspx"name="172.MEIBU.COM_WARRANT"></forms>
</authentication>
<authorization><denyusers="?"></deny></authorization>
2、 IT內部管理網項目的 Web.config用於 Form認證的設置
<machineKeyvalidationKey="AD117F2F286CDCB15A9D1D4535E16DB0248026939**AUTHOR**CITYHUNTER172****WEBSITE**172*MEIBU*COM****MAILTO**CITYHUNTER172@126*COM*****F2F286CDCB15A9D1D4535E16DB0248026939"decryptionKey="3C89AE62AD117F2F286CDCB15A9D1D4535E16DB0248026939"validation="SHA1" />
<authenticationmode="Forms">
<formsloginUrl="Login.aspx"name="172.MEIBU.COM_IT"></forms>
</authentication>
<authorization><denyusers="?"></deny></authorization>
a、兩個項目Web.cinfig的<machineKey>節點確保以下幾個欄位完全一樣:validationKey、decryptionKey、validation
b、兩個項目的 Cookie名稱必須相同,也就是 <forms>中的 name 屬性,這裡我們把它統一為name="172.MEIBU.COM_PROJECT"
c、註意區分大小寫
在整合的過程中,我把遇到的問題向大伙說一下,以免你們走同樣的路。
1、首先應該是用戶管理的問題,把兩個項目的用戶整合在一起,可不是一件容易的事,原則是新建一個新的 Table只存放帳號與密碼,用賬號做關聯,編寫觸發器,做到 Table之間的同步;
2、不要指望兩個項目間用 Session進行傳值,兩個應用程式的 Session是無法共用的。網上有人曾把類庫(編譯後的 .dll文檔)放入同一個 bin文件夾實現過 Session共用,這樣的做法實際上是把兩個項目變相合併成一個應用程式,不是我們所想要的,理由很簡單:QQ空間與 QQ音樂的伺服器分處兩地該怎麼辦?
3、項目間的傳值,可用 Cookie實現。System.Web.Security.FormsAuthentication.SetAuthCookie 方法即可實現登錄,單點登錄的實質就是含有身份驗證票的 Cookie能在項目間共用。
四、Cookie 在 ASP.NET中的用法
大家也許和我一樣,很少在 ASP.NET中使用 Cookie,傳參數呀,存變數呀,用的比較多的是 Session或ViewState以及隱藏控制項,有的乾脆用URL傳參。
1、Cookie存放的目錄
Cookie是存放在客戶端的東東,放在“Temporary Internet Files”目錄,所以說存在安全性的問題。通過以下方式找到具體位置:打開控制面板→ Internet選項 → 常規 → Internet 臨時文件→ 設置 → 即可看到“當前位置”,→ 點擊“查看文件”將直接打開該文件夾,你也可以點擊“移動文件夾”變更它所在的位置。參照下圖
2、Cookie 的有效期
從上圖我們可以清楚的看到每個 Cookie文檔的“截止期”(即為有效期)。在有效期內,當登錄電腦的用戶 Administrator再次訪問 172.meibu.com 時,那麼 IE就會在請求頁面的同時,連同上述的名稱為“Cookie:[email protected]”的Cookie文檔內容一起發送給伺服器。
若該文檔包含多個 Cookie的值時,截止期則以最後的失效期為準。
3、Cookie的類型
這裡我們按有效期來分,分為兩種:
a、即時型
指的是關閉瀏覽器(所有瀏覽 172.meibu.com的 IE)後,Cookie便失效,此類 Cookie不會在“Temporary Internet Files”目錄出現。其實它也有截止期的,為“0001-01-01”
b、持久型
就是已指定具體“截止期”的,能夠在“Temporary Internet Files”目錄裡面找到的Cookie
4、 Cookie的內容
雙擊打開“Cookie:[email protected]”,我們看到以下內容,如下圖
上圖中,“■”是換行符,所以伺服器讀出來的格式如下圖
5、在 ASP.NET頁面發放 Cookie
發送上述 Cookie的 .cs代碼為:
System.Web.HttpCookie ck =new HttpCookie("ckValue0"); ck["Author"] ="CityHunter"; ck.Expires = System.DateTime.Now.AddMinutes(10);//若不指定,則為即時型 Cookie //ck.Path="/FormTest/ManageSys"; //設置 Cookie 的虛擬路徑,註意一定要以“/”開頭,否則為無效 Cookie ;請大家自行看一下它與在客房端的 Cookie 文檔“名稱”與 “Internet 地址”的關係 Response.Cookies.Add(ck); ck = new HttpCookie("ckValue1"); //重新新建一個名為 ckValue1 的 Cookie ck.Expires = System.DateTime.Now.AddMinutes(20); //即刻起 20 分鐘後失效 ck["E_Mail"] ="[email protected]"; //設置 ckValue1 中的 E_Mail 值 ck["PersonalWeb"] ="172.meibu.com"; Response.Cookies.Add(ck); //添加此 Cookie
6、取回已發放 Cookie的值
Response.Write(Request.Cookies["ckValue0"]["Author"]+"<br>");//用不著說明瞭吧 Response.Write(Request.Cookies["ckValue1"]["E_Mail"]+"<br>"); Response.Write(Request.Cookies["ckValue1"]["PersonalWeb"]);
例子:給 Cookie賦於以下值,怎樣得到它的正確值
ck["str1"] ="2222";
ck["str"] ="str0=11111&str1=223";
可以肯定的是Request.Cookies["ckValue1"]["str"]得不到 “str0=11111&str1=223”這個字串,大家不妨試一下Request.Cookies["ckValue1"]["str1"] 會得到意想不到的字串喲。
提示:使用Server.UrlEncode()與Server.UrlDecode()
五、發放永久性的驗證 Cookie
大家登錄 CSDN的時候是否留意到一個“2周內不用再登錄”的覆選框,它又是怎麼做到的呢?大家是否曾遇到過這樣的困惑:在執行System.Web.Security.FormsAuthentication.SetAuthCookie時明明已指定createPersistentCookie為 true 為何關閉瀏覽器仍不能直接訪問網站?
System.Web.Security.FormsAuthenticationTicket tk =new System.Web.Security.FormsAuthenticationTicket(
1, //指定版本號:可隨意指定
"Admin",//登錄用戶名:對應 Web.config 中 <allow users="Admin" … /> 的 users 屬性
System.DateTime.Now, //發佈時間
System.DateTime.Now.AddYears(100), //失效時間:100 年以後,夠久了吧
false, //是否為持久 Cookie:尚未發現有何用,至少目前偶還不知,下麵會有說明
"測試用戶數據"//用戶數據:可用 ((System.Web.Security.FormsIdentity)User.Identity).Ticket.UserData 獲取
);
string str = System.Web.Security.FormsAuthentication.Encrypt(tk);//加密身份驗票
//聲明一個 Cookie,名稱為 Web.config 中 <forms name=".APSX" … /> 的 name 屬性,對應的值為身份驗票加密後的字串
System.Web.HttpCookie ck =new HttpCookie(System.Web.Security.FormsAuthentication.FormsCookieName,str);
//指定 Cookie 為 Web.config 中 <forms path="/" … /> path 屬性,不指定則預設為“/”
ck.Path=System.Web.Security.FormsAuthentication.FormsCookiePath;
//此句非常重要,少了的話,就算此 Cookie 在身份驗票中指定為持久性 Cookie ,也只是即時型的 Cookie 關閉瀏覽器後就失效;因此上面我說:我是真的還不知在身份驗票中指定為持久性 Cookie 有何用。
ck.Expires = System.DateTime.Now.AddYears(100);
Response.Cookies.Add(ck);//添加至客戶端