1. 写在最前面

    最近想写一个简单的关于权限处理的东西,之前我也了解过用二进制数的位运算可以出色地完成这个任务。关于二进制数 的位运算,常见的就是“或、与、非”这三种简单运算了,当然,我也查看了下PHP手册,还有“异或、左移、右移”这三个运算。记得上初中时数学老师就开始 唠叨个不停了,在此我也不想对此运算再作额外的说明,直接进入正题。

  2. 如何定义权限

    将权限按照2的N次方来定义值,依次类推。为什么要这样子定义呐?这样子定义保证了每个权限值(二进制)中只有一个1,而它恰好对应一种权限。比如:

    define('ADD', 1); // 增加权限
    define('UPD', 2); // 修改权限
    define('SEL', 4); // 查找权限
    define('DEL', 8); // 删除权限
  3. 权限操作

    权限操作其实涉及到“角色”这个概念。进行权限操作不外乎是让某个角色赋予某种权限、禁止某种权限和检测某个角色是否拥有某种权限。相对于这三个操作。可以用二进制数间的运算操作来很方便的实现。

    // 给予某种权限用到“位或”运算符
    $a_access = ADD | UPD | SEL | DEL; // a拥有增删改查权限
    $b_access = ADD | UPD | SEL; // b拥有增改查权限
    $c_access = ADD | UPD; // c拥有增改权限 // 禁止某种权限用“位与”和“位非”运算符
    $d_access = $c_access & ~UPD; // d只拥有了增权限 // 检测是否拥有某种权限用到“位与”运算符
    var_dump($b_access & ADD); // 1代表b拥有增权限
    var_dump($b_access & DEL); // 0代表b不拥有删权限
  4. 实现简单的权限类和角色类

    运用上面的权限操作方法,可以简单地封装成一个权限类和一个角色类。

    /**
    * 简单权限类
    * @author 27_Man
    */
    class Peak_Auth { /**
    * 权限类计数器
    * 作用在于生成权限值
    *
    * @var int
    */
    protected static $authCount = 0; /**
    * 权限名称
    *
    * @var string
    */
    protected $authName; /**
    * 权限详细信息
    *
    * @var string
    */
    protected $authMessage; /**
    * 权限值
    *
    * @var int 2的N次方
    */
    protected $authValue; /**
    * 构造函数
    * 初始化权限名称、权限详细信息以及权限值
    *
    * @param string $authName 权限名称
    * @param string $authMessage 权限详细信息
    */
    public function __construct($authName, $authMessage = '') {
    $this->authName = $authName;
    $this->authMessage = $authMessage;
    $this->authValue = 1 << self::$authCount;
    self::$authCount++;
    } /**
    * 本类不允许对象复制操作
    */
    private function __clone() { } /**
    * 设置权限详细信息
    *
    * @param string $authMessage
    */
    public function setAuthMessage($authMessage) {
    $this->authMessage = $authMessage;
    } /**
    * 获取权限名称
    *
    * @return string
    */
    public function getAuthName() {
    return $this->authName;
    } /**
    * 获取权限值
    *
    * @return int
    */
    public function getAuthValue() {
    return $this->authValue;
    } /**
    * 获取权限详细信息
    *
    * @return string
    */
    public function getAuthMessage() {
    return $this->authMessage;
    }
    } /**
    * 简单角色类
    *
    * @author 27_Man
    */
    class Peak_Role { /**
    * 角色名
    *
    * @var string
    */
    protected $roleName; /**
    * 角色拥有的权限值
    *
    * @var int
    */
    protected $authValue; /**
    * 父角色对象
    *
    * @var Peak_Role
    */
    protected $parentRole; /**
    * 构造函数
    *
    * @param string $roleName 角色名
    * @param Peak_Role $parentRole 父角色对象
    */
    public function __construct($roleName, Peak_Role $parentRole = null) {
    $this->roleName = $roleName;
    $this->authValue = 0;
    if ($parentRole) {
    $this->parentRole = $parentRole;
    $this->authValue = $parentRole->getAuthValue();
    }
    } /**
    * 获取父角色的权限
    */
    protected function fetchParenAuthValue() {
    if ($this->parentRole) {
    $this->authValue |= $this->parentRole->getAuthValue();
    }
    } /**
    * 给予某种权限
    *
    * @param Peak_Auth $auth
    * @return Peak_Role 以便链式操作
    */
    public function allow(Peak_Auth $auth) {
    $this->fetchParenAuthValue();
    $this->authValue |= $auth->getAuthValue();
    return $this;
    } /**
    * 阻止某种权限
    *
    * @param Peak_Auth $auth
    * @return Peak_Role 以便链式操作
    */
    public function deny(Peak_Auth $auth) {
    $this->fetchParenAuthValue();
    $this->authValue &= ~$auth->getAuthValue();
    return $this;
    } /**
    * 检测是否拥有某种权限
    *
    * @param Peak_Auth $auth
    * @return boolean
    */
    public function checkAuth(Peak_Auth $auth) {
    return $this->authValue & $auth->getAuthValue();
    } /**
    * 获取角色的权限值
    *
    * @return int
    */
    public function getAuthValue() {
    return $this->authValue;
    }
    }
  5. 对权限类和角色类的简单操作例子

    // 创建三个权限:可读、可写、可执行
    $read = new Peak_Auth('CanRead');
    $write = new Peak_Auth('CanWrite');
    $exe = new Peak_Auth('CanExe'); // 创建一个角色 User
    $user = new Peak_Role('User'); // 创建另一个角色 Admin,他拥有 User 的所有权限
    $admin = new Peak_Role('Admin', $user); // 给予 User 可读、可写的权限
    $user->allow($read)->allow($write); // 给予 Admin 可执行的权限,另外他还拥有 User 的权限
    $admin->allow($exe); // 禁止 Admin 的可写权限
    $admin->deny($write); // 检测 Admin 是否具有 某种权限
    var_dump($admin->checkAuth($read));
    var_dump($admin->checkAuth($write));
    var_dump($admin->checkAuth($exe));

关于PHP位运算的简单权限设计的更多相关文章

  1. Java中的位运算及简单的算法应用介绍

    众所周知,计算机底层是二进制.而java作为一门计算机编程语言,也对二进制的位运算提供了完整的支持. 在java中,int是32位的,也就是说可以用来实现32位的位运算.方便起见,我们一般用16进制对 ...

  2. java位运算之简单了解

    1.十进制转化为二进制 将正整数转化为二进制的方法“除2取余,逆序排列”. 2.二进制转化为十进制 表示整数的二进制,第一位为标志位,0代表为正整数,位数从右开始,第一个位数为0,各位位数记作n,取各 ...

  3. C语言原码反码补码与位运算.

      目录:     一.机器数和真值     二.原码,反码和补码的基础概念     三.为什么要使用原码,反码和补码     四.原码,补码,反码再深入     五.数据溢出测试     六.位运算 ...

  4. 「C语言」原码反码补码与位运算

    尽管能查到各种文献,亲自归纳出自己的体系还是更能加深对该知识的理解.     本篇文章便是在结合百度百科有关原码.反码.补码和位运算的介绍并深度借鉴了张子秋和Liquor相关文章后整理而出.   目录 ...

  5. Java位运算总结:位运算用途广泛《转》

    前天几天研究了下JDK的Collection接口,本来准备接着研究Map接口,可是一查看HashMap类源码傻眼咯,到处是位运算实现,所以我觉得还是有必要先补补位运算知识,不然代码看起来有点费力.今天 ...

  6. C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序

    C#中缓存的使用   缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可:  <%@ Outp ...

  7. C#枚举中的位运算权限分配浅谈

    常用的位运算主要有与(&), 或(|)和非(~), 比如: 1 & 0 = 0, 1 | 0 = 1, ~1 = 0 在设计权限时, 我们可以把权限管理操作转换为C#位运算来处理. 第 ...

  8. C#学习笔记-----C#枚举中的位运算权限分配

    一.基础知识 什么是位运算? 用二进制来计算,1&2:这就是位运算,其实它是将0001与0010做位预算   得到的结果是 0011,也就是3  2.位预算有多少种?(我们就将几种我们权限中会 ...

  9. C#枚举中的位运算权限分配

    什么是位运算 常用的位运算主要有与(&), 或(|)和非(~), 比如: & = ; | = ; ~ = ; 运用在权限设计中 先建立一个枚举表示所有的权限管理操作: [Flags] ...

随机推荐

  1. 【BZOJ-1858】序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1961  Solved: 991[Submit][Status ...

  2. 【poj2455】 Secret Milking Machine

    http://poj.org/problem?id=2455 (题目链接) 题意 给出一张n个点,p条边的无向图,需要从1号节点走到n号节点一共T次,每条边只能经过1次,问T次经过的最大的边最小是多少 ...

  3. wpf添加超链接

    前段: <TextBlock Margin="69,93,859,10"> <Hyperlink NavigateUri="http://dmsite. ...

  4. 根据xsd生成C#类

    var file = "1.xsd"; // Get the namespace for the schema. CodeNamespace ns = Processor.Proc ...

  5. Bmob开发指南【android端】

    作为一个开发者,数据的存储,用户的登陆,验证等操作,对程序来说是必不可少的,下面我们将从Bmob的基本信息开始讲起: [Bmob] 官网:   http://www.bmob.cn/ 帮助文档:htt ...

  6. dataGrid查询表格

    waf("#Gird").dataGrid("reloadGrid") //重新发请求去装载数据 waf("#Grid").wafGrid( ...

  7. UVa 437 The Tower of Babylon(经典动态规划)

    传送门 Description Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details ...

  8. BZOJ2186: [Sdoi2008]沙拉公主的困惑

    传送门 常规数论题,利用欧拉函数的相关性质. 题求$[1,N!]$中与$M!$互质的数的个数,且$M \leq N$.然后根据欧拉函数的相关性质很容易得出这道题的答案为$\frac{\phi (M!) ...

  9. javascript中对象字面量的理解

    javascript中对象字面量与数组字面量 第一部分 我们知道JavaScript中的数据类型有基本数据类型和引用类型,其中Object类型就是非常常用的类型.那么如果创建一个Object类型的实例 ...

  10. SQL Server编程(05)游标【转载】

    在关系数据库中,我们对于查询的思考是面向集合的.而游标打破了这一规则,游标使得我们思考方式变为逐行进行.对于类C的开发人员来着,这样的思考方式会更加舒服. 正常面向集合的思维方式是: 而对于游标来说: ...