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

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

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

权限表(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

于是,我们得到一个人所拥有的权限就是一个集合为 (类型为:List<int>)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

我们得到一个人所拥有的权限就是一个对象为 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)));

文笔不好,勿喷。

时间: 2024-08-10 02:56:11

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

JMeter非GUI方式运行时动态设置线程组及传参

在使用JMeter进行性能测试自动化时,可能会有如下需求: 1.指定运行多少线程,指定运行多少次: 2.访问的目标地址变化了,端口也变化了,需要重新指定. 上面的需求如果有GUI方式运行,这都不是问题,直接在脚本上进行修改即可以了. 但是性能测试自动化是以非GUI方式运行的,如果要修改测试计划就比较麻烦了. 下面来说说如何简单的搞定这些问题: 1.指定运行多少线程   我们知道JMeter测试计划在运行Sampler之前先加载运行属性(jmeter.properties,system.prope

二叉树(3)----后序遍历,递归和非递归方式

1.二叉树定义 typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct BTreeNode_t_ { BTreeNodeElement_t *m_pElemt; struct BTreeNode_t_ *m_pLeft; struct BTreeNode_t_ *m_pRight; } BTreeNode_t; 2.后序遍历 定义: 给定根节点,首先遍历左子树,然后遍历右子树,最后

ADO.NET 连接方式和非链接方式访问数据库

//连接方式访问数据库的主要步骤 1.创建连接对象(l链接字符串) 2.创建命令对象(设置Command对象的几个属性值) 3.打开连接 4.发送命令 5.处理数据 6.关闭连接 //非链接方式访问数据库 1/创建连接对象 2.创建数据适配器对象 3.打开连接 4.发送命令 5.关闭连接

Android 使用OpenCV之编译环境非CygWin方式(Win7+Eclipse+ADT+CDT+NDK)

本文完全基于官网: https://dl-ssl.google.com/android/eclipse/ 只有简单的三步,官网写的非常简明全面,非常佩服 [准备] 1. Eclipse(Indigo) 2. ADT: 这个不说了,无非就是eclipse添加个android的安装源,如果这里选择了NDK Plugin的话,就会自动安装CDT哟: 3. NDK(android-ndk-r9d-windows-x86_64) 地址: http://developer.android.com/tools

ADO.NET 非连接方式进行数据访问

1. 配置 DataAdapter 以检索信息 1.1. DataAdapter ? 数据适配器是数据集与数据源交互的桥梁 –使相当于数据源本地拷贝的数据集可以与数据源之间进行交互. ? 为数据库提供的主要两种数据适配器 – SqlDataAdapter:不经过OLEDB层直接与SQLServer交互,速度较OleDbDataAdapter快. – OleDbDataAdapter:适用于任何可以用OLEDB数据提供者访问的数据源. 1.2. XxxDataAdapter对象模型 ? Comma

链表反转(递归方式,非递归方式)

//非递归方式进行链表反转 public ListNode reverseList(ListNode head){ if(head==null||head.next==null){ return head; }else { ListNode pre=head; ListNode p=head.next; ListNode next=null; while (p!=null) { next=p.next; p.next=pre; pre=p; p=next; } head.next=null; r

非链接方式访问数据库--查询的数据集用Dataset来存储。

private void Button_Click_1(object sender, RoutedEventArgs e) { //非链接方式访问数据库, //1创建连接对象(连接字符串) using (SqlConnection conn = new SqlConnection(SQLHelper.ConnectionString)) { //2.创建数据适配器对象 using (SqlDataAdapter sda = new SqlDataAdapter("select * from St

11g使用非duplicate方式创建物理standby要注意的问题总结

在上篇博文中,使用了duplicate方式来创建物理standby http://blog.csdn.net/aaron8219/article/details/38434579 今天来说说在11g中採用非duplicate方式创建备库碰到的一些问题,并做个总结. 在10g中,通常能够使下面几种方法创建备库控制文件 RMAN> backup current controlfile for standby format 'c:\ctl_%U'; RMAN> backup full databas

【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结

从上一篇的springmvc入门中已经看到,springmvc.xml中的配置了映射器和适配器,是使用非注解的方式来配置的,这是非注解方式的一种,这里再复习一下: 1. 非注解方式 1.1 处理器适配器 上一节中使用的处理器适配器是:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.即: SimpleControllerHandlerAdapter适配器能执行实现了Controller接口的Handler,所以我