Community Server
專(zhuān)題十:
MemberRole
之
RoleManager
由于最近忙于一些瑣事,近半個(gè)月都沒(méi)有寫(xiě)新的專(zhuān)題,今天忙里抽閑趕緊補(bǔ)上,實(shí)在是抱歉。
設(shè)計(jì)做多了就會(huì)發(fā)現(xiàn),用戶權(quán)限管理是一個(gè)永恒的話題,幾乎沒(méi)有什么項(xiàng)目不需要權(quán)限和角色管理的,可能會(huì)無(wú)數(shù)次去寫(xiě)角色管理的代碼,而且會(huì)根據(jù)項(xiàng)目的不同粒度也會(huì)有所不同。在
CS
中,采用了
MemberRole.dll
中的
RoleManager
進(jìn)行角色管理,該角色管理機(jī)制同樣在
asp.net 2.0 beta2
中得到應(yīng)用。在分析代碼之前先看看數(shù)據(jù)庫(kù)中的角色的關(guān)系表:
表分兩種前綴,一種是“ aspnet_ ”另一種是“ cs_ ”,“ aspnet_ ”是采用 MemberRole.dll 組件所必需的一些表,包括過(guò)程和視圖等都是這樣命名的,在 asp.net 2.0 beta2 中你也可以看到同樣的表、視圖與儲(chǔ)存過(guò)程。“ cs_ ”前綴是 CS 系統(tǒng)需要的表,由此可以看到 MemberRole.dll 中的 RoleManager 只管理到角色級(jí)別,通常我們還會(huì)給角色添加一些權(quán)限,然后在應(yīng)用系統(tǒng)中判斷角色擁有的權(quán)限從而決定用戶是否有訪問(wèn)的權(quán)限,當(dāng)然一個(gè)用戶可以有多個(gè)角色,一個(gè)角色又可以有多個(gè)權(quán)限。有時(shí)你設(shè)計(jì)的某些系統(tǒng)是不需要做如此多權(quán)限管理的,只要多個(gè)角色就可以解決問(wèn)題,那么就不再需要擴(kuò)展數(shù)據(jù)庫(kù),直接使用 MemberRole.dll 中的 RoleManager 就可以了。
注意:你可能會(huì)對(duì) cs_SectionPermissions 、 cs_ProductPermissions 表產(chǎn)生疑惑,這里有兩個(gè)權(quán)限表,分別管理兩種權(quán)限, cs_SectionPermissions 中存儲(chǔ)節(jié)點(diǎn)級(jí)別的權(quán)限,如 Blog 中,是否有權(quán)限開(kāi)通 blog ,管理所有 blog 等,這些權(quán)限就放在 cs_SectionPermissions ,但是對(duì)于每個(gè) blog ,如我的 blog ,現(xiàn)在不想要某個(gè)用戶訪問(wèn),或者需要某個(gè)用戶幫忙管理,再或者某個(gè)地方某些用戶可以訪問(wèn),某些不行,這樣的權(quán)限就放入 cs_ProductPermissions 中設(shè)置。
RoleManager 是一個(gè) HttpModule ,由此可以在 web.config 中看到如下的配置文件:
?
<
add?
name
="RoleManager"
?type
="Microsoft.ScalableHosting.Security.RoleManagerModule,?MemberRole,?Version=1.0.0.0,?Culture=neutral,?PublicKeyToken=b7c773fb104e7562"
?
/>
?
這也是 RoleManager 角色管理的入口點(diǎn),同時(shí),在 RoleManager 中實(shí)現(xiàn)了 IConfigurationSectionHandler 接口,用來(lái)讀取 Web.config 中的以下配置:
????????
<
roleManager?
??????????????
cacheRolesInCookie
="true"
?cookieName
=".CSRoles"
?cookieTimeout
="90"
??????????????cookiePath
="/"
??cookieRequireSSL
="false"
?cookieSlidingExpiration
="true"
?
??????????????createPersistentCookie
="true"
?cookieProtection
="All"
?maxCachedResults
="1000"
?
>
??????????????
<
providers
>
???????????????????
<
add
???????????????????????
name
="CommunityServerSqlProvider"
???????????????????????type
="CommunityServer.Components.CSRoleProvider,?CommunityServer.Components"
???????????????????????connectionStringName
="SiteSqlServer"
???????????????????????applicationName
="dev"
???????????????????????description
="Stores?and?retrieves?roles?data?from?the?local?Microsoft?SQL?Server?database"
?
???????????????????
/>
??????????????
</
providers
>
?????
</
roleManager
>
?????
再這里我們又看到了 Provider 模型,其實(shí) asp.net 2.0 beta2 中大量使用了這種數(shù)據(jù)訪問(wèn)模型。它的優(yōu)點(diǎn)我在前面的專(zhuān)題中已經(jīng)講解過(guò),不理解的朋友可以看我之前的專(zhuān)題。
在 RoleManager 很重要的一個(gè)類(lèi)就是:
該類(lèi)繼承至
IPrincipal
,因此我們可以在用戶登錄后通過(guò)檢查當(dāng)前
Context
中
User
的一些方法和屬性,判斷擁護(hù)是否擁有某角色。操作的方法在
RoleMangerModule
類(lèi)下的
OnEnter
下:
private
?
void
?OnEnter(
object
?source,?EventArgs?eventArgs)
{
??????
if
?(Roles.Enabled)
??????
{
????????????HttpContext?context1?
=
?((HttpApplication)?source).Context;
????????????
if
?(context1.User?
==
?
null
)
????????????
{
??????????????????context1.User?
=
?
new
?GenericPrincipal(
new
?GenericIdentity(
string
.Empty,?
string
.Empty),?
new
?
string
[
0
]);
????????????}
????????????
if
?(
this
._eventHandler?
!=
?
null
)
????????????
{
??????????????????RoleManagerEventArgs?args1?
=
?
new
?RoleManagerEventArgs(context1);
??????????????????
this
._eventHandler(
this
,?args1);
??????????????????
if
?(args1.RolesPopulated)
??????????????????
{
????????????????????????
return
;
??????????????????}
????????????}
????????????
if
?(Roles.CacheRolesInCookie)
????????????
{
??????????????????
if
?(context1.User.Identity.IsAuthenticated?
&&
?(
!
Roles.CookieRequireSSL?
||
?context1.Request.IsSecureConnection))
??????????????????
{
????????????????????????
try
????????????????????????
{
??????????????????????????????HttpCookie?cookie1?
=
?context1.Request.Cookies[Roles.CookieName];
??????????????????????????????
if
?(cookie1?
!=
?
null
)
??????????????????????????????
{
????????????????????????????????????
string
?text1?
=
?cookie1.Value;
????????????????????????????????????
if
?((text1?
!=
?
null
)?
&&
?(text1.Length?
>
?
0x1000
))
????????????????????????????????????
{
??????????????????????????????????????????Roles.DeleteCookie();
????????????????????????????????????}
????????????????????????????????????
else
????????????????????????????????????
{
??????????????????????????????????????????
if
?(((Roles.CookiePath?
!=
?
null
)?
&&
?(Roles.CookiePath.Length?
>
?
0
))?
&&
?(Roles.CookiePath?
!=
?
"
/
"
))
??????????????????????????????????????????
{
????????????????????????????????????????????????cookie1.Path?
=
?Roles.CookiePath;
??????????????????????????????????????????}
??????????????????????????????????????????cookie1.Domain?
=
?Roles.Domain;
??????????????????????????????????????????context1.User?
=
?
new
?RolePrincipal(context1.User.Identity,?text1);
????????????????????????????????????}
??????????????????????????????}
????????????????????????}
????????????????????????
catch
????????????????????????
{
????????????????????????}
??????????????????}
??????????????????
else
?
if
?(context1.Request.Cookies[Roles.CookieName]?
!=
?
null
)
??????????????????
{
????????????????????????Roles.DeleteCookie();
??????????????????}
????????????}
????????????
if
?(
!
(context1.User?
is
?RolePrincipal))
????????????
{
??????????????????context1.User?
=
?
new
?RolePrincipal(context1.User.Identity);
????????????}
??????}
}
由于知識(shí)點(diǎn)比較簡(jiǎn)單, 在 MSDN 上也有相關(guān)的 IPrincipal 與 Identity 的介紹,我就不細(xì)細(xì)的分析。
在 RoleManger 里,很多地方使用了 Cookie ,這樣做提高了不少的效率,你想,如果每個(gè)用戶每次訪問(wèn)一個(gè)頁(yè)面都去讀一次數(shù)據(jù)庫(kù),把該訪問(wèn)用戶的權(quán)限讀取出來(lái),也許你聰明點(diǎn),把該用戶的權(quán)限先緩存在內(nèi)存中,并且設(shè)置一定的過(guò)期時(shí)間,其實(shí)你還能再聰明一點(diǎn),那就是把角色保存在客戶端的 Cookie ,這樣連服務(wù)器的內(nèi)存都節(jié)約了。只有在用戶第一次登錄,或者清除了 Cookie 等 Cookie 失效的情況下才需要訪問(wèn)數(shù)據(jù)庫(kù)。但是這也帶來(lái)一個(gè)問(wèn)題,就是如果客戶端禁止使用 Cookie ,用戶將無(wú)法正常訪問(wèn)。 CS 中通過(guò)在 web.config 中可以配置是否啟用這種機(jī)制。
到這里,整個(gè) MemberRole.dll 算是粗略的講解了一遍,由于時(shí)間上的限制不可能滿足所有讀者的要求,如果有疑問(wèn)可以 msn 我或者給我留言。后面一些專(zhuān)題我將說(shuō)說(shuō) CS 的頁(yè)面,包括 MasterPage 、 Theme 、 Skin 等機(jī)制。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

