zoukankan      html  css  js  c++  java
  • 第二章 基于二进制进行权限管理的理论知识

    源代码GitHub:https://github.com/ZhaoRd/Zrd_0001_AuthorityManagement

    1.介绍

          第一章主要是介绍了这个DEMO的来由和主要使用的技术,这章内容主要是介绍如何通过二进制的位运算进行权限控制的内容。

          第一章发布之后,有不少网友、园友反映程序代码运行不起来,很感谢您们的反馈,刚刚进行了代码修复,已经同步到github,感兴趣的朋友可以加我QQ!

    2.二进制的位运算以及如何进行权限判断

          基于二进制的权限管理,这个内容是我在两年前接触到过的一个知识,在这里重温一下。

          2.1位运算

                用二进制进行权限管理,那么首先要知道的内容是如何通过位运算来进行权限操作的。权限操作,我个人认为有 授权、取消授权和验证这三个操作。利用二进制的或运算来实现授权操作;利用二进制的先求补、在求与来实现取消授权的操作;利用与运算实现权限的验证操作。

           先说明一下二进制的与(&)、或(|)、求补(~)运算:     

           或(|)运算的内容有:  1|1 =1 、1|0=1  、0|1=1、0|0=0. 通过或运算可以看出,只要有一个数位为1,那么所求结果就为1.

           与(&)运算的内容有: 1&1 =1 、1&0=0、0&1=0、0&0=0,通过与运算可以看出,只要有一数为0,那么所求结果就为0.

           求补(~)运算的内容有  ~1=0、~0=1,求补运算表面上看起来就是 1和0倒转过来。

           2.2 权限内容

           我们假设采用8位二进制代表具体的权限集合具体关系如下:

          |  下载   |  打印   |  查看   |  审核    |  详细  |  删除  |   编辑  |   创建 |

          |     0     |     0     |     0     |     0      |     0    |    0     |      0    |     0    |

          如果某位为0,这表示没有改操作权限,如果为1,这表示具有该操作权限,比如: 0000 0001 表示只有创建权限、00100011这表示有创建、编辑、查看着三种操作权限,依次类推。

           如果用一个整数来代表一个操作权限的话,那么

           创建=1、编辑=2、删除=4、详细=8、审核=16、查看=32、打印=64、下载=128、全部=255(前面所有内容相加)、无=0。

           那么数字3(00000011)则表示有创建和编辑的权限,13(00001101)折表示有详细、创建、编辑这三种操作权限。

           2.3 授权操作

            如果一个功能已经有了 创建和编辑的权限,二进制就是 0000 0011 ,这么现在要添加一个查看(0010 0000)权限,授权之后的权限的二进制就为(0010 0011),通过2.1的内容可知,当

        0000 0011

    |  0010 0000

    -----------------

        0010 0011,

    这样就通过了或运算添加给原有的权限添加一个新的权限

          2.4 取消授权操作

          如果一个功能已经有了查看、创建、编辑的权限,二进制就是 0010 0011 ,现在要求要取消编辑的权限,取消授权之后的二进制就是: 0010 0001 ,整个内容看起来就是对编辑位进行求反运算,那么我们先看编辑权限的求补运算的结果: 

    ~ 0000 0010

    ----------------

        1111 1101 ,

    那么求补的结果在和原有权限进行和运算 

        (0010 0011)

    & (1111 1101)

    -----------------

        (0010 0001) ,

    这样就得到了取消之后的二进制 0010 0001(17)

            2.5 权限判断

            现在要判断 0011 1100 这个代表的权限操作中,有没有审核权限(0001 0000),那么我们对这两个权限进行 与运算 

    (0011 1100)

    & (0001 0000)

    -------------------------

            (0001 0000),

    判断有没有创建权限(0000 0001),

             (0011 1100)

         & (0000 0001)

    --------------------------

             0000 0000,

    也就是说,两个权限进行与运算,如果与运算的结果为0,则表示无该操作,反正,则表示具有该操作。

    3.源代码

      3.1 权限代码(枚举)

        

    /// <summary>
    
    /// 定义权限.
    
    /// </summary>
    
    [Flags]
    
    public enum PermissionValue
    
    {
    
    /// <summary>
    
    /// The create.
    
    /// </summary>
    
    [EnumDescription("创建")]
    
    Create = 1,
    
     
    
    /// <summary>
    
    /// The edit.
    
    /// </summary>
    
    [EnumDescription("编辑")]
    
    Edit = 2,
    
     
    
    /// <summary>
    
    /// The delete.
    
    /// </summary>
    
    [EnumDescription("删除")]
    
    Delete = 4,
    
     
    
    /// <summary>
    
    /// The detail.
    
    /// </summary>
    
    [EnumDescription("详细")]
    
    Detail = 8,
    
     
    
    /// <summary>
    
    /// The audit.
    
    /// </summary>
    
    [EnumDescription("审核")]
    
    Audit = 16,
    
     
    
    /// <summary>
    
    /// The lookup.
    
    /// </summary>
    
    [EnumDescription("查看")]
    
    Lookup = 32,
    
     
    
    /// <summary>
    
    /// The print.
    
    /// </summary>
    
    [EnumDescription("打印")]
    
    Print = 64,
    
     
    
    /// <summary>
    
    /// The download.
    
    /// </summary>
    
    [EnumDescription("下载")]
    
    Download = 128,
    
    
    /// <summary>
    
    /// The all.
    
    /// </summary>
    
    [EnumDescription("全部")]
    
    All = Create | Edit | Delete | Detail | Audit | Lookup | Print | Download,
    
     
    
    /// <summary>
    
    /// The none.
    
    /// </summary>
    
    [EnumDescription("无")]
    
    None = 0
    
    }
    

      

            3.2 权限操作代码

    /// <summary>
    
    /// 权限验证.
    
    /// </summary>
    
    /// <param name="toVerification">
    
    /// 需要验证的权限.
    
    /// </param>
    
    /// <param name="functionInRole">
    
    /// 已经存在的权限.
    
    /// </param>
    
    /// <returns>
    
    /// The <see cref="bool"/>.
    
    /// </returns>
    
    public bool VerifyPermission(PermissionValue toVerification,
    
    PermissionValue functionInRole)
    
    {
    
    return (toVerification & functionInRole) != 0;
    
    }
    
     
    
    /// <summary>
    
    /// 权限验证.
    
    /// </summary>
    
    /// <param name="functionId">
    
    /// 功能ID.
    
    /// </param>
    
    /// <param name="roleId">
    
    /// 角色ID.
    
    /// </param>
    
    /// <param name="toVerification">
    
    /// The 需要验证的权限.
    
    /// </param>
    
    /// <returns>
    
    /// The <see cref="bool"/>.
    
    /// </returns>
    
    public bool VerifyPermission(Guid functionId,
    
    Guid roleId,PermissionValue toVerification)
    
    {
    
     
    
    var spec = Specification<FunctionInRole>.Eval(u => u.Role.ID == roleId && u.Function.ID == functionId);
    
     
    
    var isexist = this.functionInRoleRepository.Exists(spec);
    
     
    
    // 不存在则表示未授权
    
    if (!isexist)
    
    {
    
    return false;
    
    }
    
     
    
    var functionInRole = this.functionInRoleRepository.Find(spec);
    
     
    
    return this.VerifyPermission(toVerification,functionInRole.PermissionValue);
    
    }
    
     
    
    /// <summary>
    
    /// 增加权限.
    
    /// </summary>
    
    /// <param name="functionId">
    
    /// 功能ID.
    
    /// </param>
    
    /// <param name="roleId">
    
    /// 角色ID.
    
    /// </param>
    
    /// <param name="toAddPermission">
    
    /// 需要添加的权限.
    
    /// </param>
    
    public void AddAuthority(Guid functionId, Guid roleId, PermissionValue toAddPermission)
    
    {
    
    this.GuardAuthorityAgum(functionId,roleId, toAddPermission);
    
     
    
    var spec = Specification<FunctionInRole>.Eval(u => u.Role.ID == roleId && u.Function.ID == functionId);
    
    
    
    var isexist = this.functionInRoleRepository.Exists(spec);
    
    if (!isexist)
    
    {
    
    // 如果未进行过授权,这进行第一次授权
    
    var role = this.roleRepository.GetByKey(roleId);
    
    var function = this.functionRepository.GetByKey(functionId);
    
    this.functionInRoleRepository.Add(new FunctionInRole()
    
    {
    
    ID = GuidHelper.GenerateGuid(),
    
    Role = role,
    
    Function = function,
    
    PermissionValue = toAddPermission
    
    });
    
    }
    
    else
    
    {
    
    // 如果已经进行过授权,则在原有权限上增加新权限
    
    var functionInRole = this.functionInRoleRepository.Find(spec);
    
     
    
    // 或运算实现授权
    
    functionInRole.PermissionValue |= toAddPermission;
    
    this.functionInRoleRepository.Update(functionInRole);
    
    }
    
     
    
    // TODO:unitofwork模式
    
    this.functionInRoleRepository.Context.Commit();
    
    }
    
     
    
    /// <summary>
    
    /// 删除权限.
    
    /// </summary>
    
    /// <param name="functionId">
    
    /// 功能ID.
    
    /// </param>
    
    /// <param name="roleId">
    
    /// 角色ID.
    
    /// </param>
    
    /// <param name="toRemovePermission">
    
    /// 需要移除的权限.
    
    /// </param>
    
    /// <exception cref="Exception">
    
    /// 未授权
    
    /// </exception>
    
    public void DeleteAuthority(Guid functionId,Guid roleId, PermissionValue toRemovePermission)
    
    {
    
    var spec = Specification<FunctionInRole>.Eval(u => u.Role.ID == roleId
    
    && u.Function.ID == functionId);
    
     
    
    var isexist = this.functionInRoleRepository.Exists(spec);
    
    if (!isexist)
    
    {
    
    throw new Exception("尚未赋予权限");
    
    }
    
     
    
    var functionInRole = this.functionInRoleRepository.Find(spec);
    
     
    
    // 求补和与运算实现权限移除:value= value&(~toremove)
    
    functionInRole.PermissionValue &= ~toRemovePermission;
    
    this.functionInRoleRepository.Update(functionInRole);
    
     
    
    // TODO:应当使用unitofwork模式
    
    // 领域服务是否依赖仓储?
    
    this.functionInRoleRepository.Context.Commit();
    
    }
    
     
    
    /// <summary>
    
    /// 检验角色、功能是否存在和功能点是否能够对某种权限进行操作.
    
    /// </summary>
    
    /// <param name="functionId">
    
    /// 功能ID.
    
    /// </param>
    
    /// <param name="roleId">
    
    /// 角色ID.
    
    /// </param>
    
    /// <param name="permissionValue">
    
    /// 待验证权限.
    
    /// </param>
    
    /// <exception cref="Exception">
    
    /// </exception>
    
    private void GuardAuthorityAgum(Guid functionId,
    
    Guid roleId, PermissionValue permissionValue)
    
    {
    
    
    
    var functionIsExist = this.functionRepository.Exists(Specification<Function>.Eval(f => f.ID == functionId));
    
    var roleIsExist = this.roleRepository.Exists(Specification<Role>.Eval(u => u.ID == roleId));
    
     
    
    if (!functionIsExist || !roleIsExist)
    
    {
    
    throw new Exception("功能或角色不存在,请检查参数信息");
    
    }
    
     
    
    var function = this.functionRepository.GetByKey(functionId);
    
    if (!this.VerifyPermission(permissionValue, function.PermissionValue))
    
    {
    
    throw new Exception("该模块功能不具有需要添加的权限,禁止添加");
    
    }
    
    }
    

      

    4. 总结

            本章主要是阐述了如何使用二进制的位运算进行权限操作的,包括授权、取消授权、验证这三种操作。通过二进制的或运算可以达到授权的操作,通过求补和与运算,可以实现取消授权的操作,通过与运算,可以实现权限验证的操作。

            下一章内容,主要是介绍项目结构,包括如何分层、类库之间的引用关系等内容。

    推荐QQ群:

    278252889(AngularJS中文社区)

    5008599(MVC EF交流群)

    134710707(ABP架构设计交流群 )

    59557329(c#基地 )

    230516560(.NET DDD基地 )

    本人联系方式:QQ:351157970

  • 相关阅读:
    java.lang.AbstractMethodError: com.microsoft.jdbc.base.BaseDatabaseMetaData.supportsGetGeneratedKeys()Z
    安装oracle后java -version命令显示 jdk version "1.3.1"的原因
    jquery 获取和设置Select选项常用方法总结
    select动态增加option
    Jquery detect page refresh
    HibernateTemplate 查询
    The dialect was not set. Set the property hibernate.dialect
    hibernate的异常 Session was already closed
    <c:forEach>取得集合数量
    Jstl标签<c:forEach>的用法
  • 原文地址:https://www.cnblogs.com/zhaord/p/4839877.html
Copyright © 2011-2022 走看看