原文地址:http://yumincq.blog.163.com/blog/static/50776820108395417220/?fromdm&fromSearch&isFromSearchEngine=yes
幾乎所有的系統中都會使用到存取控制和角色管理這樣的功能,例如:建立、修改、刪除使用者和角色,為使用者指派角色,管理角色中的使用者等等。於是MS在ASP.NET 2.0開始,實現了這些功能,使得我們在開發中,不需要考慮這方面的內容,把更多的精力投入到商務邏輯的開發中去。從而大大的提高了開發的效率。下面我們就來學習一下如何使用membership。
1.添加資料庫支援
要使用membership首先需要資料庫的支援,所以我們第一步就是建立用來存放使用者、角色等資訊的表結構。別擔心,MS早就把建立表的語句寫好了,並且還提供了使用者介面,讓我們點點滑鼠就可以建立好所需的結構了。
具體操作如下:進入C:\WINDOWS\Microsoft.NET\Framework\v2.0.xxxxx(vs2010的目錄是v4.0.xxxx)這個目錄下,找到aspnet_regsql.exe直接雙擊運行,就會彈出一個介面,直接下一步。第二個介面讓我們選擇是添加表結構還是移除,我們當然選擇添加,繼續下一步。在這個介面中需要填寫伺服器ip地址以及身分識別驗證資訊。在填寫完畢後,就可以選擇你要將表結構添加到哪個資料庫中了。需要注意的是:如果選擇預設,則會建立一個新的名叫aspnetdb的資料庫,然後將表結構加入其中。一路下一步就完成了資料庫結構的添加。
2.web.config配置
好了,表結構添加完畢,接下來就是需要在項目中進行一些簡單的配置了。我們在vs中建立一個網站,隨後再用記事本開啟C:\WINDOWS\Microsoft.NET\Framework\v2.0.xxxxx\CONFIG\machine.config這個檔案,找到system.web節點下的membership節點,將整個節點複製到我們建立網站的web.config中的system.web節點中。
複製過來的代碼如下:
<membership>
<providers>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""/>
</providers>
</membership>
下面是主要的幾個屬性的含義:
name:資料提供者的名稱,由於我們是從machine.config複製過來的,所以必須改名,防止重名
type:資料提供者類型,如果使用的是MSSQL資料庫,則保持不變即可,如果使用的是Oracle等其他資料庫,則必須自己建立一個類來繼承MembershipProvider抽象基類,重寫裡邊的所有抽象方法,然後把類型寫在這裡即可。
connectionStringName:該屬性必須指定在<connectionStrings>節點中,一個連接字串的名字。
applicationName:應用程式名稱,membership允許多個應用程式共同使用一個資料庫來管理自己的使用者、角色資訊,各應用程式只需配置不同的applicationName即可,當然,如果想要多個應用程式使用同一份使用者角色資訊,只需設定一樣的applicationName即可。
requiresUniqueEmail:顧名思義,使用者註冊時,是否需要提供未註冊過的郵箱。
passwordFormat:密碼儲存格式,密碼儲存在資料庫中的格式,最常用的有Clear(不加密)和Hashed(使用SHA1演算法加密)
minRequiredPasswordLength:最小密碼長度。
minRequiredNonalphanumericCharacters:指定有效密碼中必須包含的特殊字元的最小數量,就是說不是字母也不是數位字元的數量,比如+-*/,.什麼的,增加密碼強度
好了,我們將配置修改一下並添加連接字串:
<connectionStrings>
<add name="ConnectionString" connectionString="server=.;uid=sa;pwd=sa;database=aspnetdb"/>
</connectionStrings>
<system.web>
<membership defaultProvider="mySqlMembershipProvider">
<providers>
<add name="mySqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="ConnectionString"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
applicationName="TestMembership"
requiresUniqueEmail="true"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""/>
</providers>
</membership>
</system.web>
上面用黃色高亮字型標註出來的屬性,是為了告訴membership採用我們剛才添加的mySqlMembershipProvider這個配置,因為machine.config中有一個AspNetSqlMembershipProvider,我們又在web.config中又添加了一個mySqlMembershipProvider,現在有了兩個配置,所以應該使用defaultProvider屬性指明本網站使用哪個配置。隨後又指定了連接字串配置的名稱,一個Email不允許重複註冊,最小密碼長度為6,不限制密碼中必須含有標點符號等配置。
3.ASP.NET身分識別驗證配置
membership算是配置到這裡了,但是還沒有結束,我們還需要把ASP.NET的身分識別驗證機制配置為Forms身分識別驗證。
補充內容:
ASP.NET一共有三種身分識別驗證方式,分別為:
Forms驗證
Windows驗證
Passport驗證
Windows驗證是一種把能夠訪問到IIS的使用者認為是已經通過身分識別驗證的使用者。可以通過windows內建的身分識別驗證策略來控制哪些頁面使用者可以訪問,哪些不能訪問。這是一種最簡單的方式,基本不用寫多少代碼,全部通過配置就可以實現訪問的控制。
Passport驗證是由微軟提供驗證服務。當然這是收費的。
Forms驗證就是在使用者登入時,向瀏覽器中添加一個cookie,然後在使用者每次訪問時都檢測這個cookie,從而達到身分識別驗證的目的。
配置Forms身分識別驗證其實就是把下面代碼複製到web.config中去就可以了:
<system.web>
<authentication mode="Forms">
<forms loginUrl="Login.aspx"
protection="All"
timeout="30"
name=".ASPXAUTH"
path="/"
slidingExpiration="true"
defaultUrl="default.aspx"
cookieless="UseDeviceProfile"/>
</authentication>
</system.web>
下面是說明(msdn抄的):
loginUrl 指嚮應用程式的自訂登入頁。應該將登入頁放在需要安全通訊端層 (SSL) 的檔案夾中。這有助於確保憑據從瀏覽器傳到 Web 服務器時的完整性。
protection 設定為 All,以指定表單身分識別驗證票的保密性和完整性。這導致使用 machineKey 元素上指定的演算法對身分識別驗證票證進行加密,並且使用同樣是 machineKey 元素上指定的雜湊演算法進行簽名。
timeout 用於指定表單身分識別驗證會話的有限生存期。預設值為 30 分鐘。如果頒發持久的表單身分識別驗證 Cookie,timeout 屬性還用於設定持久 Cookie 的生存期。
name 和 path 設定為應用程式的設定檔中定義的值。
requireSSL 設定為 false。該配置意味著身分識別驗證 Cookie 可通過未經 SSL 加密的通道進行傳輸。如果擔心會話竊取,應考慮將 requireSSL 設定為 true。
slidingExpiration 設定為 true 以執行變化的會話生存期。這意味著只要使用者在網站上處於活動狀態,會話逾時就會定期重設。
defaultUrl 設定為應用程式的 Default.aspx 頁。
cookieless 設定為 UseDeviceProfile,以指定應用程式對所有支援 Cookie 的瀏覽器都使用 Cookie。如果不支援 Cookie 的瀏覽器訪問該網站,表單身分識別驗證在 URL 上打包身分識別驗證票。
enableCrossAppRedirects 設定為 false,以指明表單身分識別驗證不支援自動處理在應用程式之間傳遞的查詢字串上的票證以及作為某個表單 POST 的一部分傳遞的票證。
需要說明一下的是LoginUrl和DefaultUrl屬性:LoginUrl指向登入頁面,當ASP.NET判斷出該使用者請求的資源不允許匿名訪問,而該使用者未登入時,ASP.NET會自動跳轉到LoginUrl所指向的頁面,當登入成功後,則跳回原來請求的頁面。DefaultUrl指向預設頁面。當我們直接存取登入頁面,並登入成功後,這時ASP.NET會跳轉到DefaultUrl指向的頁面。其他的選項不寫都可以,因為有預設值。
上篇講到如何配置membership以及ASP.NET Forms身分識別驗證,本篇將對許可權控制部分,做一個詳細的解釋。
在所有的基本配置都完畢後,我們還需要配置哪些目錄允許被匿名訪問,哪些是需要使用者登入後允許訪問的頁面。
首先:我們在項目中建立一個admin檔案夾,在admin檔案夾中添加一個web.config檔案,然後在其中的<system.web>節點下面添加如下代碼:
<authorization>
<allow users="admin"/>
<deny users="*"/>
</authorization>
然後我們在admin目錄下再添加一個頁面,然後訪問該頁面,看一下效果。如果您按照我們上篇所說的內容全部正確配置了,那麼你會發現,頁面並沒有顯示出來,而是跳轉到了我們之前在<authentication>下<forms>節點的LoginUrl屬性所指向的頁面,要求登入!這不就是我們需要的效果嗎?
現在來解釋一下上面配置的含義:
<allow>節點:顧名思義就是允許訪問的意思,<allow users="admin"/>就是允許使用者名稱為"admin"的使用者訪問。
<deny>節點:就是禁止訪問。這裡用到了一個萬用字元“*”,萬用字元有兩個:*代表所有使用者,還有一個“?”代表所有匿名使用者。所以<deny users="*"/>就是不允許所有使用者訪問的意思啦,當然如果是:<deny users="?"/>那意思就是不允許所有匿名使用者存取。
需要說明的是:所有的配置都是按照從上到下的順序來匹配的,一但匹配成功,就不再向下匹配。舉個例子:
<authorization>
<allow users="admin"/>
<allow users="zhangsan"/>
<deny users="*"/>
</authorization>
ASP.NET首先檢測當前登入的使用者名稱=="admin"?如果等於則不繼續判斷,直接允許該使用者訪問。如果不等於則繼續判斷當前登入的使用者名稱=="zhangsan"等於,則允許訪問,不等於則接著向下,讀取到了<deny users="*"/>這個配置,拒絕所有使用者訪問,跳轉到LoginUrl指定的頁面要求重新登入。
可是如果這樣,只能實現目錄一級的許可權控制,如果要控制某個檔案的存取權限,又該如何做呢?難道非得把這個檔案放到一個檔案夾中,然後再添加web.config進行控制嗎?答案是否定的,對於單個檔案的存取控制,ASP.NET也有相應的配置:
<configuration>
<location path="a.aspx">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
<system.web>
<authorization>
<allow users="admin"/>
<allow users="zhangsan"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
看上面這個配置,我們可以在<system.web>節點之上(必須是上面)再增加一個<location>節點,通過path屬性指明location內的配置是單獨針對哪個檔案即可。具體內容我就不多說了,想必大家也都看得懂。不過需要注意的一點就是:location節點可以有多個。這意味著同一個目錄下的不同檔案可以有不同的存取權限。
好了,配置到這裡算是完成一多半了。還有一個問題就是:如果我們的使用者比較多,那麼需要在設定檔中把這些使用者全部羅列其中。並且以後添加了新使用者,還得繼續修改配置,太麻煩了!該怎麼辦呢?通用的做法就是引入角色的概念。給所有的使用者指派一個角色,比如:users,admin等。然後我們只需要控制這些角色的存取權限即可。以後添加了新使用者只需給這個新使用者指派角色,而不用去修改配置,實在是方便。其實,membership也提供了角色的概念,只需要簡單的配置一下就可以實現了。
要實現角色功能,非常簡單,我們還是去machine.config的<system.web>節點下面找到<roleManager>節點,然後整個節點複製過來到web.config中去,一般會有兩個<add>子結點,我們刪除一個,留下一個就可以了。全部內容如下:
<roleManager>
<providers>
<add name="AspNetSqlRoleProvider"
connectionStringName="LocalSqlServer"
applicationName="/"
type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</roleManager>
這個配置比較簡單,各項配置和前面配置都一樣,不再多說。稍微修改一下:
<roleManager enabled="true" defaultProvider="myAspNetSqlRoleProvider">
<providers>
<add name="myAspNetSqlRoleProvider"
connectionStringName="ConnectionString"
applicationName="TestMembership"
type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</roleManager>
注意:這個roleManager多了個屬性enable="true",這是因為角色管理預設情況下是關閉的,所以我們必須得設定為開啟才行。