權限管理
權限管理,一般指根據系統設置的安全規則或者安全策略,用戶可以訪問而且只能訪問自己被授權的資源,不多不少。權限管理幾乎出現在任何系統里面,只要有用戶和密碼的系統。權限管理還是比較復雜的,有的固定到某個模塊,某個操作,甚至是某個按鈕,總之想要做好一個權限管理,真的很不容易,一直在探索當中,全當拋磚引玉;看到網上好多關於權限管理的文章,以前也寫過簡單的文章,今天樓主我也要總結整理一下自己的實現方法,畢竟一千個讀者就有一千個哈姆雷特,說說自己的詳細實現、基本設計和基本思想希望幫到入門的新人們。
一、基本的數據庫表設計
基本的表設計如圖,用戶表、角色表、模塊表、權限表和用戶角色關系表、角色模塊權限關系表,某個用戶的角色(管理員、用戶等),然后再去判斷對應角色的模塊(新聞、文章等)權限(增、刪、改、查)。
創建基本權限操作的SQL腳本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
CREATE
TABLE
[dbo].[Module](
[ID] [
int
] IDENTITY(1,1)
PRIMARY
KEY
NOT
NULL
,
[ModuleKey] [nvarchar](100)
NOT
NULL
,
[ModuleName] [nvarchar](100)
NOT
NULL
,
)
CREATE
TABLE
[dbo].[Permission](
[ID] [
int
] IDENTITY(1,1)
PRIMARY
KEY
NOT
NULL
,
[PermissionKey] [nvarchar](100)
NOT
NULL
,
[PermissionName] [nvarchar](100)
NOT
NULL
,
)
CREATE
TABLE
[dbo].[Role](
[ID] [
int
] IDENTITY(1,1)
PRIMARY
KEY
NOT
NULL
,
[RoleName] [nvarchar](100)
NOT
NULL
,
)
CREATE
TABLE
[dbo].[RoleModulePermission](
[ID] [
int
] IDENTITY(1,1)
PRIMARY
KEY
NOT
NULL
,
[RoleID] [
int
]
NOT
NULL
,
[ModuleID] [
int
]
NOT
NULL
,
[PermissionID] [
int
]
NOT
NULL
,
)
CREATE
TABLE
[dbo].[
User
](
[ID] [
int
] IDENTITY(1,1)
PRIMARY
KEY
NOT
NULL
,
[AccountNum] [nvarchar](100)
NOT
NULL
,
[Pwd] [nvarchar](100)
NOT
NULL
,
[Status] [
int
]
NOT
NULL
,
[LastLoginTime] [datetime]
NOT
NULL
,
[Remark] [nvarchar](100)
NULL
,
)
CREATE
TABLE
[dbo].[UserRole](
[ID] [
int
] IDENTITY(1,1)
PRIMARY
KEY
NOT
NULL
,
[UserID] [
int
]
NOT
NULL
,
[RoleID] [
int
]
NOT
NULL
,
)
|
二、代碼中具體的實現
這是一個基類,所有的Controller都繼承BaseController,[UserAuthorizeFilter(Order = 999)],每一個Action過濾器都有一個 Order 屬性,用來決定Action過濾器在該范圍內的執行順序。Order屬性必需是0(默認值)或者更大的整數值。省略Order屬性則會給該過濾器的Order值為 -1, 表明為指明順序。任何一個在同一范圍的Action過濾器Order設為 -1 的都將按不確定的順序執行,單在此之前過濾器有一個特定的順序。登錄的時候是存儲的加密的Cookie,會有一個私鑰(自己定義)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
[UserAuthorizeFilter(Order = 999)]
public
class
BaseController : Controller
{
public
int
LoginID {
get
;
set
; }
public
string
LoginName {
get
;
set
; }
/// <summary>
/// 是否登錄的標志
/// </summary>
/// <returns></returns>
public
bool
IsLogin()
{
if
(NCookieUtil.GetCookie(
"GkqCMSCookie"
) !=
null
)
{
string
cookie_ver = NCookieUtil.GetCookie(
"GkqCMSCookie"
);
string
[] cookieArray = cookie_ver.Split(
'&'
);
int
loginId = cookieArray[1].ToInt();
string
token = cookieArray[0].ObjectToString();
Admin_User user = AdminPermissionRepository.Get(loginId);
if
(user !=
null
)
{
string
tokenKey =
string
.Format(
"{0}{1}{2}{3}"
, user.ID.ObjectToString(), user.AccountNum.ObjectToString(), user.Pwd.ObjectToString(), CommonHelper.SecretSalt);
if
(token == tokenKey)
{
LoginID = user.ID;
LoginName = user.AccountNum;
return
true
;
}
return
false
;
}
return
false
;
}
else
{
return
false
;
}
}
}
|
Filter里面判斷用戶是否登錄cb.IsLogin(),如果登陸驗證通過還要驗證是否對某個某個Controller對應的Action有操作權限。如果未登錄或者發成錯誤底層會捕獲,跳轉到登陸頁面或者是錯誤頁。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
public
class
UserAuthorizeFilter : System.Web.Mvc.AuthorizeAttribute
{
public
override
void
OnAuthorization(AuthorizationContext filterContext)
{
BaseController cb = filterContext.Controller
as
BaseController;
if
(!cb.IsLogin())
{
SetHttpContext(filterContext, GkmBBS.DataCenter.GlobalEnumHelper.EnumJsonResult.NotLogin,
"未登錄"
);
}
else
{
bool
IsAuthorization = filterContext.Controller.TempData[
"IsAuthorization"
].ToBoolean(
true
);
if
(IsAuthorization)
{
string
controller = filterContext.RouteData.Values[
"controller"
].ObjectToString();
string
action = filterContext.RouteData.Values[
"action"
].ObjectToString();
if
(!AdminPermissionRepository.IsPowerPage(cb.LoginID,controller, action))
{
SetHttpContext(filterContext, GkmBBS.DataCenter.GlobalEnumHelper.EnumJsonResult.NoAccess,
"您沒有權限執行此操作"
);
}
}
}
}
private
void
SetHttpContext(AuthorizationContext filterContext, GkmBBS.DataCenter.GlobalEnumHelper.EnumJsonResult result,
string
msg)
{
if
(filterContext.HttpContext.Request.IsAjaxRequest())
{
var
data =
new
{ Result = (
int
)result, Msg = msg };
filterContext.Result =
new
JsonpResult() { Data = data, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
else
{
if
(result == GkmBBS.DataCenter.GlobalEnumHelper.EnumJsonResult.NotLogin)
{
filterContext.Result =
new
RedirectResult(
string
.Format(
"/Login/Index?ReturnUrl={0}"
, filterContext.HttpContext.Request.Url.OriginalString));
}
else
{
filterContext.Controller.ViewData[
"ErrorMessage"
] = msg;
filterContext.Result =
new
ViewResult() { ViewName =
"Error"
, ViewData = filterContext.Controller.ViewData };
}
}
}
}
|
用戶的ID判斷角色,然后把角色去查是否有這個權限,如果有進入,對應的controller 和action,如果沒有則沒權限。具體實現方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public
static
bool
IsPowerPage(
int
loginID,
string
Moudle,
string
operate)
{
try
{
string
sql =
string
.Format(
@"SELECT COUNT(1)
FROM (
SELECT c.modulekey,
d.permissionkey
FROM (
SELECT *
FROM Admin_userrole
WHERE userid = {0}
) a
LEFT JOIN Admin_RoleModulePermission b
ON a.roleId = b.roleId
LEFT
JOIN Admin_Module c
ON b.moduleId = c.Id
LEFT JOIN Admin_Permission d
ON b.PermissionId = d.Id
) e
WHERE e.moduleKey = '{1}'
AND e.PermissionKey = '{2}'"
, loginID, Moudle, operate);
return
NSqlHelper.ExecuteScalar(NWebConfig.ReadConnectionString(DBCon.SYS_DBCONNSTRING), CommandType.Text, sql,
null
).ToInt() > 0;
}
catch
(Exception ex)
{
log.Error(
"AdminPermissionRepository-IsPowerPage"
, ex);
return
false
;
}
}
|
用戶登錄成功寫入Cookie,然后瀏覽每個模塊判斷登錄和具體某個模塊的權限, 這算是一個最基本簡單權限管理,適合新手入門用,