新聞中心
淺談基于URL的權(quán)限控制ASP.NET MVC中的實(shí)現(xiàn)

10年積累的網(wǎng)站建設(shè)、網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有松山免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
在數(shù)據(jù)庫(kù)中新建2個(gè)表。PermissionItem表用于保存權(quán)限ID和頁(yè)面路徑的關(guān)系,一個(gè)權(quán)限ID可以有多個(gè)頁(yè)面,一般同一個(gè)權(quán)限ID下的頁(yè)面是為了實(shí)現(xiàn)同一個(gè)功能。PermissionList表用于保存用戶所具有的權(quán)限。
- Code
- USE [UrlAuthorize]
- GO
- /****** Object: Table [dbo].[PermissionList] Script Date: 07/07/2009 00:07:10 ******/
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE TABLE [dbo].[PermissionList](
- [ID] [int] IDENTITY(1,1) NOT NULL,
- [PermissionID] [int] NOT NULL,
- [UserID] [int] NOT NULL,
- CONSTRAINT [PK_PermissionList] PRIMARY KEY CLUSTERED
- (
- [ID] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
- SET IDENTITY_INSERT [dbo].[PermissionList] ON
- INSERT [dbo].[PermissionList] ([ID], [PermissionID], [UserID]) VALUES (1, 2, 1)
- INSERT [dbo].[PermissionList] ([ID], [PermissionID], [UserID]) VALUES (2, 3, 1)
- SET IDENTITY_INSERT [dbo].[PermissionList] OFF
- /****** Object: Table [dbo].[PermissionItem] Script Date: 07/07/2009 00:07:10 ******/
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- SET ANSI_PADDING ON
- GO
- CREATE TABLE [dbo].[PermissionItem](
- [ID] [int] IDENTITY(1,1) NOT NULL,
- [PermissionID] [int] NOT NULL,
- [Name] [nvarchar](50) NOT NULL,
- [Route] [varchar](100) NOT NULL,
- CONSTRAINT [PK_PermissionItem] PRIMARY KEY CLUSTERED
- (
- [ID] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- ) ON [PRIMARY]
- GO
- SET ANSI_PADDING OFF
- GO
- SET IDENTITY_INSERT [dbo].[PermissionItem] ON
- INSERT [dbo].[PermissionItem] ([ID], [PermissionID], [Name], [Route]) VALUES (1, 1, N'測(cè)試頁(yè)1', N'/Test/Page1')
- INSERT [dbo].[PermissionItem] ([ID], [PermissionID], [Name], [Route]) VALUES (2, 2, N'測(cè)試頁(yè)2', N'/Test/Page2')
- INSERT [dbo].[PermissionItem] ([ID], [PermissionID], [Name], [Route]) VALUES (3, 3, N'測(cè)試頁(yè)3', N'/Test/Page3')
- INSERT [dbo].[PermissionItem] ([ID], [PermissionID], [Name], [Route]) VALUES (5, 1, N'測(cè)試頁(yè)4', N'/Test/Page4')
- INSERT [dbo].[PermissionItem] ([ID], [PermissionID], [Name], [Route]) VALUES (6, 2, N'測(cè)試頁(yè)5', N'/Test/Page5')
- SET IDENTITY_INSERT [dbo].[PermissionItem] OFF
數(shù)據(jù)庫(kù)中的示例表示Page1和Page4同屬于權(quán)限1,Page2和Page5同屬于權(quán)限2,Page3屬于權(quán)限3。用戶ID為1的用戶具有權(quán)限2和3。
在ASP.NET MVC項(xiàng)目中新建一個(gè)AccountHelper類,這是一個(gè)輔助類。GetPermissionItems方法用于獲取權(quán)限ID和頁(yè)面路徑的對(duì)應(yīng)關(guān)系。這是全局的,并且每個(gè)用戶在訪問(wèn)頁(yè)面時(shí)都會(huì)用到這些信息,所以存入Cache中。數(shù)據(jù)庫(kù)的相關(guān)操作這里使用的是ADO.NET Entity Framework。
1/**////
2/// 獲取權(quán)限項(xiàng)
3///
4///權(quán)限項(xiàng)列表
5public static ListGetPermissionItems()
6{
7 // 如果緩存中已經(jīng)存在權(quán)限列表信息,則直接從緩存中讀取。
8 if (HttpContext.Current.Cache["PermissionItems"] == null)
9 {
10 // 如果緩存中沒(méi)有權(quán)限列表信息,則從數(shù)據(jù)庫(kù)獲取并寫入緩存
11 UrlAuthorizeEntities db = new UrlAuthorizeEntities();
12 var items = db.PermissionItem.Where(c => c.PermissionID > 0).ToList();
13 HttpContext.Current.Cache["PermissionItems"] = items;
14 }
15
16 // 這個(gè)緩存中保存了所有需要進(jìn)行權(quán)限控制的頁(yè)面所對(duì)應(yīng)的權(quán)限ID
17 return (List)HttpContext.Current.Cache["PermissionItems"];
18}
19
GetUserPermission方法是將用戶所具有的權(quán)限ID保存到一個(gè)一維Int32數(shù)組中。這個(gè)信息每個(gè)用戶是不同的,但是會(huì)經(jīng)常使用到,所以存入Session。
1/**////
2/// 獲取用戶權(quán)限
3///
4/// 用戶ID
5///用戶權(quán)限數(shù)組
6public static Int32[] GetUserPermission(int userID)
7{
8 // 如果緩存中已經(jīng)存在權(quán)限列表信息,則直接從緩存中讀取。
9 if (HttpContext.Current.Session["Permission"] == null)
10 {
11 // 從數(shù)據(jù)庫(kù)獲取用戶權(quán)限并將權(quán)限ID放到int數(shù)組并存入Session
12 UrlAuthorizeEntities db = new UrlAuthorizeEntities();
13 var permissions = db.PermissionList.Where(c => c.UserID == userID).Select(c=>c.PermissionID).ToArray();
14 HttpContext.Current.Session["Permission"] = permissions;
15 }
16 return (Int32[])HttpContext.Current.Session["Permission"];
17}
18
再新建一個(gè)UrlAuthorizeAttribute類,繼承自AuthorizeAttribute,這是一個(gè)Filter。我們重寫它的OnAuthorization方法,以在ASP.NET頁(yè)生命周期身份驗(yàn)證階段執(zhí)行它。
1/**////
2/// 重寫OnAuthorization
3///
4///
5public override void OnAuthorization(AuthorizationContext filterContext)
6{
7 // 獲取權(quán)限項(xiàng)列表
8 ListpItems = AccountHelper.GetPermissionItems();
9
10 // 獲取當(dāng)前訪問(wèn)頁(yè)面對(duì)應(yīng)的權(quán)限ID。如果item為空則表示當(dāng)前頁(yè)面沒(méi)有權(quán)限控制信息,不需要進(jìn)行權(quán)限控制
11 var item = pItems.FirstOrDefault(c => c.Route == filterContext.HttpContext.Request.Path);
12
13 if (item != null)
14 {
15 if (Array.IndexOf(AccountHelper.GetUserPermission(int.Parse(filterContext.HttpContext.Session["UserID"].ToString())), item.PermissionID) == -1)
16 {
17 // 提示權(quán)限不夠,也可以跳轉(zhuǎn)到其他頁(yè)面
18 filterContext.HttpContext.Response.Write("沒(méi)有權(quán)限訪問(wèn)該頁(yè)面");
19 filterContext.HttpContext.Response.End();
20 }
21 }
22 else
23 {
24 // 如果權(quán)限項(xiàng)列表中不存在當(dāng)前頁(yè)面對(duì)應(yīng)的權(quán)限ID則所有用戶都不允許訪問(wèn),直接提示無(wú)權(quán)訪問(wèn)。***注1***
25 filterContext.HttpContext.Response.Write("沒(méi)有權(quán)限訪問(wèn)該頁(yè)面");
26 filterContext.HttpContext.Response.End();
27 }
28}
29
至此,主要的工作都已經(jīng)完成了的。接下來(lái)我們只需要在需要進(jìn)行基于URL權(quán)限控制的Action或Controller前加上[UrlAuthorize],這些Action或Controller中的所有Actions就會(huì)自動(dòng)被UrlAuthorize這個(gè)Filter進(jìn)行處理。如果某一個(gè)Action被標(biāo)上了[UrlAuthorize],而數(shù)據(jù)庫(kù)中又不存在該頁(yè)面對(duì)應(yīng)的權(quán)限ID,那么根據(jù)示例的代碼,所有用戶都將無(wú)法訪問(wèn)這個(gè)頁(yè)面,如果需要更改這個(gè)設(shè)置,可以修改上面“注1”下面的2行代碼。
新聞名稱:淺談基于URL的權(quán)限控制ASP.NETMVC中的實(shí)現(xiàn)
文章來(lái)源:http://m.fisionsoft.com.cn/article/djodood.html


咨詢
建站咨詢
