热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用二进制与或非的方式进行权限分配

我们一般的思路设计一个权限系统是这样的:假设有个游戏如果同时大拇指点击,中指点击,小指点击就会暴击权限表(T_Right),字段(C_RightId,C_RightName)用户权限分配表

我们一般的思路设计一个权限系统是这样的:

假设有个游戏如果同时大拇指点击,中指点击,小指点击就会暴击

权限表(T_Right),字段(C_RightId,C_RightName)

用户权限分配表(T_UserRights),字段(C_UserId,C_RightId)

测试数据如下:

 1 /****** Object:  Table [dbo].[T_Right]    Script Date: 2016/6/4 10:43:18 ******/
 2 SET ANSI_NULLS ON
 3 GO
 4 SET QUOTED_IDENTIFIER ON
 5 GO
 6 SET ANSI_PADDING ON
 7 GO
 8 CREATE TABLE [dbo].[T_Right](
 9     [C_RightId] [int] NOT NULL,
10     [C_RightName] [varchar](50) NOT NULL,
11  CONSTRAINT [PK_T_Right] PRIMARY KEY CLUSTERED 
12 (
13     [C_RightId] ASC
14 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
15 ) ON [PRIMARY]
16 
17 GO
18 SET ANSI_PADDING OFF
19 GO
20 /****** Object:  Table [dbo].[T_UserRights]    Script Date: 2016/6/4 10:43:18 ******/
21 SET ANSI_NULLS ON
22 GO
23 SET QUOTED_IDENTIFIER ON
24 GO
25 CREATE TABLE [dbo].[T_UserRights](
26     [C_UserId] [int] NOT NULL,
27     [C_RightId] [int] NOT NULL,
28  CONSTRAINT [PK_T_UserRights] PRIMARY KEY CLUSTERED 
29 (
30     [C_UserId] ASC,
31     [C_RightId] ASC
32 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
33 ) ON [PRIMARY]
34 
35 GO
36 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (1, N'大拇指点击')
37 GO
38 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (2, N'食指点击')
39 GO
40 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (3, N'中指点击')
41 GO
42 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (4, N'无名指点击')
43 GO
44 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (5, N'小指点击')
45 GO
46 INSERT [dbo].[T_UserRights] ([C_UserId], [C_RightId]) VALUES (1, 1)
47 GO
48 INSERT [dbo].[T_UserRights] ([C_UserId], [C_RightId]) VALUES (1, 2)
49 GO
50 INSERT [dbo].[T_UserRights] ([C_UserId], [C_RightId]) VALUES (1, 3)
51 GO
52 INSERT [dbo].[T_UserRights] ([C_UserId], [C_RightId]) VALUES (1, 4)
53 GO
54 INSERT [dbo].[T_UserRights] ([C_UserId], [C_RightId]) VALUES (1, 5)
55 GO
View Code

 于是,我们得到一个人所拥有的权限就是一个集合为 (类型为:List)userRights:

select * from [dbo].[T_UserRights] where C_UserId=1

 

C_UserId    C_RightId
----------- -----------
1           1
1           2
1           3
1           4
1           5

(5 行受影响)

 

我们要判判断用户是否有 暴击权限的时候,可能会这样判断:

 1 List<int> userRights = DataBase.GetUserRightsById(1);
 2 List<int> bjRights = DataBase.GetBJRights();
 3 bool hasbjrights = true;
 4 foreach(var right in bjRights)
 5 {
 6   if (userRights.Contains(right))
 7   {     
 8       hasbjrights = false;
 9       break;
10   }
11 }
12 if (hasbjrights)
13 {
14                 //有权限
15 }
16 else
17 {
18                 //无权限
19 }


此方法的特点是判断是否同时拥有 暴击 权限就需要两层循环判断(应该也有其他方法)。

当然另外一个思路是(用户权限分配表(T_UserRights),字段(C_UserId,C_RightId)),C_RightId为字符串类型,

权限存储形式为: 1   1,3,5   一个用户的权限用一个字符串存储就行了) 当然也是需要两层循环判断。

下面说下我的方法:

数据库设计如下:

 1 /****** Object:  Table [dbo].[T_Right]    Script Date: 2016/6/4 11:29:57 ******/
 2 SET ANSI_NULLS ON
 3 GO
 4 SET QUOTED_IDENTIFIER ON
 5 GO
 6 SET ANSI_PADDING ON
 7 GO
 8 CREATE TABLE [dbo].[T_Right](
 9     [C_RightId] [int] NOT NULL,
10     [C_RightName] [varchar](50) NOT NULL,
11  CONSTRAINT [PK_T_Right] PRIMARY KEY CLUSTERED 
12 (
13     [C_RightId] ASC
14 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
15 ) ON [PRIMARY]
16 
17 GO
18 SET ANSI_PADDING OFF
19 GO
20 /****** Object:  Table [dbo].[T_UserRights]    Script Date: 2016/6/4 11:29:57 ******/
21 SET ANSI_NULLS ON
22 GO
23 SET QUOTED_IDENTIFIER ON
24 GO
25 CREATE TABLE [dbo].[T_UserRights](
26     [C_UserId] [int] NOT NULL,
27     [C_Rights] [int] NOT NULL,
28  CONSTRAINT [PK_T_UserRights_1] PRIMARY KEY CLUSTERED 
29 (
30     [C_UserId] ASC
31 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
32 ) ON [PRIMARY]
33 
34 GO
35 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (1, N'大拇指点击')
36 GO
37 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (2, N'食指点击')
38 GO
39 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (4, N'中指点击')
40 GO
41 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (8, N'无名指点击')
42 GO
43 INSERT [dbo].[T_Right] ([C_RightId], [C_RightName]) VALUES (16, N'小指点击')
44 GO
45 INSERT [dbo].[T_UserRights] ([C_UserId], [C_Rights]) VALUES (1, 31)
46 GO
View Code

们得到一个人所拥有的权限就是一个对象为 userRight(UserId,Rights):

select * from [dbo].[T_UserRights] where C_UserId=1

 

C_UserId    C_Rights
----------- -----------
1           31

(1 行受影响)

 这个设计跟上面的设计都表示UserId为1的用户拥有所有的权限

原因是:将权限拆为二进制表示:

C_RightId   C_RightName
----------- --------------------------------------------------
00001           大拇指点击
00010           食指点击
00100           中指点击
01000           无名指点击
10000           小指点击

(5 行受影响)

 

所有权限或的结果就是11111,就是31
我们要判判断用户是否有 暴击权限的时候,代码如下:

 1 int Rights = DataBase.GetUserRightById(1);
 2 int bjRight = DataBase.GetBJRight();
 3 if ((Rights & bjRight) == Rights)
 4 {
 5                 //有权限
 6 }
 7  else
 8 {
 9                 //无权限
10 }

 这样做,在进行逻辑处理的时候只要进行与或即可。方便,效率也高。

缺点也是有的,就是最大的权限的值会以2的指数增长,那么权限多的时候这个值有无可能装不下

灵感来源:System.Windows.Forms.Control.Anchor,对于winform熟悉的朋友应该知道这个属性吧:

获取或设置控件绑定到的容器的边缘并确定控件如何随其父级一起调整大小。

 1     //
 2     // 摘要:
 3     //     指定控件如何锚定到其容器的边缘。
 4     [Flags]
 5     public enum AnchorStyles
 6     {
 7         //
 8         // 摘要:
 9         //     该控件未锚定到其容器的任何边缘。
10         NOne= 0,
11         //
12         // 摘要:
13         //     该控件锚定到其容器的上边缘。
14         Top = 1,
15         //
16         // 摘要:
17         //     该控件锚定到其容器的下边缘。
18         Bottom = 2,
19         //
20         // 摘要:
21         //     该控件锚定到其容器的左边缘。
22         Left = 4,
23         //
24         // 摘要:
25         //     该控件锚定到其容器的右边缘。
26         Right = 8
27     }

表示控件同时根据父控件的上,左,右进行调整大小 代码如下:
  this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); 

文笔不好,勿喷。


推荐阅读
  • 微软平台的软件开发系统中,有着一套自己的约定规则。熟悉.net开发的都会对异常处理不陌生,现阶段的各种编程语言中,都不乏异常处理机制,个中原理也都大同小异。sqlserver在批处 ... [详细]
  • 这篇文章主要讲解了“SQLServer与Access数据库ASP代码有什么区别”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深 ... [详细]
  • 关于SQLSERVER的全文目录跟全文索引的区别
    很久没有写随笔了,本来之前想写一篇关于SQLSERVER全文索引的随笔,可惜没有时间,一直拖到现在才有时间写,不好意思让各位久等了~先介绍一下SQLSERVER中的存储类对象,哈哈,先介绍一下概念嘛 ... [详细]
  • 转载:http:www.crazycoder.cnDataBaseIndex.html查询速度慢的原因很多,常见如下几种:1、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设 ... [详细]
  • 本文档提供了详细的MySQL安装步骤,包括解压安装文件、选择安装类型、配置MySQL服务以及设置管理员密码等关键环节,帮助用户顺利完成MySQL的安装。 ... [详细]
  • SQLite是一种轻量级的关系型数据库管理系统,尽管体积小巧,却能支持高达2TB的数据库容量,每个数据库以单个文件形式存储。本文将详细介绍SQLite在Android开发中的应用,包括其数据存储机制、事务处理方式及数据类型的动态特性。 ... [详细]
  • SQL 数据恢复技巧:利用快照实现高效恢复
    本文详细介绍了如何在 SQL 中通过数据库快照实现数据恢复,包括快照的创建、使用及恢复过程,旨在帮助读者深入了解这一技术并有效应用于实际场景。 ... [详细]
  • 本文详细介绍了如何处理Oracle数据库中的ORA-00227错误,即控制文件中检测到损坏块的问题,并提供了具体的解决方案。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 定制数据层关键字:数据层,访问,元数据,数据访问模型http://www.gaodaima.com/35448.html定制数据层_sqlserver ... [详细]
  • SQLServer2008全套 数据库简介,分离,收缩,快照
    第三课视频笔记:联机丛书的使用附加和分离数据库---收缩数据库--------数据库快照 ... [详细]
  • SqlServer分区表概述(转载)
    什么是分区表一般情况下,我们建立数据库表时,表数据都存放在一个文件里。但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件 ... [详细]
  • php5.3.x访问sqlserver2005
    由于项目需要,临时用php访问Sqlserver数据库,于是配置mssql扩展,但是无法访问,按照网上各种dll文件copy都不成功,最后终于发现是php版本问题,我的版本是php5.3 ... [详细]
  • 本文主要介绍关于asp.net,visualstudio,sqlserver的知识点,对【asp.net小说网站案例】和【asp.net电商项目】有兴趣的朋友可以看下由【师哥帮忙】投稿的技术文章,希 ... [详细]
  • 1.3.4ProfilerSQLServerProfiler是一个图形化的管理工具用于监督记录和检查SQLServer数据库的使用情况对系统管理员来说它是一个监视用户活动的间谍1. ... [详细]
author-avatar
西乡塘化民以精神
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有