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


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

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

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

    文笔不好,勿喷。

  • 相关阅读:
    mysql零碎问题合集
    mysql 纵表转横表 需要用join不能直接where连接
    eclipse导出可执行jar包 报main function not found错误
    shell脚本将mysql查询结果制作成csv格式
    linux shell中把句子中的单词提取作为变量值 主要是使用了数组
    linux下文件字符编码转换
    Banner使用
    recyclerview的博客网址需要的权限
    okhttp权限
    Okhttp代码
  • 原文地址:https://www.cnblogs.com/dishiyicijinqiu/p/5558333.html
Copyright © 2020-2023  润新知