浅析关于PHP位运算的简单权限设计
程序员文章站
2022-06-13 14:50:49
1.写在最前面最近想写一个简单的关于权限处理的东西,之前我也了解过用二进制数的位运算可以出色地完成这个任务。关于二进制数的位运算,常见的就是“或、与、非”这三种简单运算了,...
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.实现简单的权限类和角色类
运用上面的权限操作方法,可以简单地封装成一个权限类和一个角色类。
/**
* 简单权限类
*/
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手册,还有“异或、左移、右移”这三个运算。记得上初中时数学老师就开始唠叨个不停了,在此我也不想对此运算再作额外的说明,直接进入正题。
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.实现简单的权限类和角色类
运用上面的权限操作方法,可以简单地封装成一个权限类和一个角色类。
复制代码 代码如下:
/**
* 简单权限类
*/
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));
上一篇: apache日志文件详解和实用分析命令