ThinkPHP权限认证Auth实例详解
来源:互联网 发布:godaddy域名续费好贵 编辑:程序博客网 时间:2024/06/17 06:27
本文以实例代码的形式深入剖析了ThinkPHP权限认证Auth的实现原理与方法,具体步骤如下:
mysql数据库部分sql代码:
-- ----------------------------
-- Table structure for think_auth_group
-- ----------------------------
DROP
TABLE
IF EXISTS `think_auth_group`;
CREATE
TABLE
`think_auth_group` (
`id` mediumint(8) unsigned
NOT
NULL
AUTO_INCREMENT,
`title`
char
(100)
NOT
NULL
DEFAULT
''
,
`status` tinyint(1)
NOT
NULL
DEFAULT
'1'
,
`rules`
char
(80)
NOT
NULL
DEFAULT
''
,
PRIMARY
KEY
(`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2
DEFAULT
CHARSET=utf8 COMMENT=
'用户组表'
;
-- ----------------------------
-- Records of think_auth_group
-- ----------------------------
INSERT
INTO
`think_auth_group`
VALUES
(
'1'
,
'管理组'
,
'1'
,
'1,2'
);
-- ----------------------------
-- Table structure for think_auth_group_access
-- ----------------------------
DROP
TABLE
IF EXISTS `think_auth_group_access`;
CREATE
TABLE
`think_auth_group_access` (
`uid` mediumint(8) unsigned
NOT
NULL
COMMENT
'用户id'
,
`group_id` mediumint(8) unsigned
NOT
NULL
COMMENT
'用户组id'
,
UNIQUE
KEY
`uid_group_id` (`uid`,`group_id`),
KEY
`uid` (`uid`),
KEY
`group_id` (`group_id`)
) ENGINE=MyISAM
DEFAULT
CHARSET=utf8 COMMENT=
'用户组明细表'
;
-- ----------------------------
-- Records of think_auth_group_access
-- ----------------------------
INSERT
INTO
`think_auth_group_access`
VALUES
(
'1'
,
'1'
);
INSERT
INTO
`think_auth_group_access`
VALUES
(
'1'
,
'2'
);
-- ----------------------------
-- Table structure for think_auth_rule
-- ----------------------------
DROP
TABLE
IF EXISTS `think_auth_rule`;
CREATE
TABLE
`think_auth_rule` (
`id` mediumint(8) unsigned
NOT
NULL
AUTO_INCREMENT,
`
name
`
char
(80)
NOT
NULL
DEFAULT
''
COMMENT
'规则唯一标识'
,
`title`
char
(20)
NOT
NULL
DEFAULT
''
COMMENT
'规则中文名称'
,
`status` tinyint(1)
NOT
NULL
DEFAULT
'1'
COMMENT
'状态:为1正常,为0禁用'
,
`type`
char
(80)
NOT
NULL
,
`condition`
char
(100)
NOT
NULL
DEFAULT
''
COMMENT
'规则表达式,为空表示存在就验证,不为空表示按照条件验证'
,
PRIMARY
KEY
(`id`),
UNIQUE
KEY
`
name
` (`
name
`)
) ENGINE=MyISAM AUTO_INCREMENT=5
DEFAULT
CHARSET=utf8 COMMENT=
'规则表'
;
-- ----------------------------
-- Records of think_auth_rule
-- ----------------------------
INSERT
INTO
`think_auth_rule`
VALUES
(
'1'
,
'Home/index'
,
'列表'
,
'1'
,
'Home'
,
''
);
INSERT
INTO
`think_auth_rule`
VALUES
(
'2'
,
'Home/add'
,
'添加'
,
'1'
,
'Home'
,
''
);
INSERT
INTO
`think_auth_rule`
VALUES
(
'3'
,
'Home/edit'
,
'编辑'
,
'1'
,
'Home'
,
''
);
INSERT
INTO
`think_auth_rule`
VALUES
(
'4'
,
'Home/delete'
,
'删除'
,
'1'
,
'Home'
,
''
);
DROP
TABLE
IF EXISTS `think_user`;
CREATE
TABLE
`think_user` (
`id`
int
(11)
NOT
NULL
,
`username`
varchar
(30)
DEFAULT
NULL
,
`
password
`
varchar
(32)
DEFAULT
NULL
,
`age` tinyint(2)
DEFAULT
NULL
,
PRIMARY
KEY
(`id`)
) ENGINE=InnoDB
DEFAULT
CHARSET=utf8;
-- ----------------------------
-- Records of think_user
-- ----------------------------
INSERT
INTO
`think_user`
VALUES
(
'1'
,
'admin'
,
'21232f297a57a5a743894a0e4a801fc3'
,
'25'
);
配置文件Application\Common\Conf\config.php部分:
<?php
return
array
(
//'配置项'=>'配置值'
'DB_DSN'
=>
''
,
// 数据库连接DSN 用于PDO方式
'DB_TYPE'
=>
'mysql'
,
// 数据库类型
'DB_HOST'
=>
'localhost'
,
// 服务器地址
'DB_NAME'
=>
'thinkphp'
,
// 数据库名
'DB_USER'
=>
'root'
,
// 用户名
'DB_PWD'
=>
'root'
,
// 密码
'DB_PORT'
=> 3306,
// 端口
'DB_PREFIX'
=>
'think_'
,
// 数据库表前缀
'AUTH_CONFIG'
=>
array
(
'AUTH_ON'
=> true,
//认证开关
'AUTH_TYPE'
=> 1,
// 认证方式,1为时时认证;2为登录认证。
'AUTH_GROUP'
=>
'think_auth_group'
,
//用户组数据表名
'AUTH_GROUP_ACCESS'
=>
'think_auth_group_access'
,
//用户组明细表
'AUTH_RULE'
=>
'think_auth_rule'
,
//权限规则表
'AUTH_USER'
=>
'think_user'
//用户信息表
)
);
项目Home控制器部分Application\Home\Controller\IndexController.class.php代码:
<?php
namespace
Home\Controller;
use
Think\Controller;
class
IndexController
extends
Controller {
public
function
index() {
$Auth
=
new
\Think\Auth();
//需要验证的规则列表,支持逗号分隔的权限规则或索引数组
$name
= MODULE_NAME .
'/'
. ACTION_NAME;
//当前用户id
$uid
=
'1'
;
//分类
$type
= MODULE_NAME;
//执行check的模式
$mode
=
'url'
;
//'or' 表示满足任一条规则即通过验证;
//'and'则表示需满足所有规则才能通过验证
$relation
=
'and'
;
if
(
$Auth
->check(
$name
,
$uid
,
$type
,
$mode
,
$relation
)) {
die
(
'认证:成功'
);
}
else
{
die
(
'认证:失败'
);
}
}
}
以上这些代码就是最基本的验证代码示例。
下面是源码阅读:
1、权限检验类初始化配置信息:
$Auth
=
new
\Think\Auth();
创建一个对象时程序会合并配置信息
程序会合并Application\Common\Conf\config.php中的AUTH_CONFIG数组
public
function
__construct() {
$prefix
= C(
'DB_PREFIX'
);
$this
->_config[
'AUTH_GROUP'
] =
$prefix
.
$this
->_config[
'AUTH_GROUP'
];
$this
->_config[
'AUTH_RULE'
] =
$prefix
.
$this
->_config[
'AUTH_RULE'
];
$this
->_config[
'AUTH_USER'
] =
$prefix
.
$this
->_config[
'AUTH_USER'
];
$this
->_config[
'AUTH_GROUP_ACCESS'
] =
$prefix
.
$this
->_config[
'AUTH_GROUP_ACCESS'
];
if
(C(
'AUTH_CONFIG'
)) {
//可设置配置项 AUTH_CONFIG, 此配置项为数组。
$this
->_config =
array_merge
(
$this
->_config, C(
'AUTH_CONFIG'
));
}
}
2、检查权限:
check(
$name
,
$uid
,
$type
= 1,
$mode
=
'url'
,
$relation
=
'or'
)
大体分析一下这个方法
首先判断是否关闭权限校验 如果配置信息AUTH_ON=>false 则不会进行权限验证 否则继续验证权限
if
(!
$this
->_config[
'AUTH_ON'
]) {
return
true;
}
获取权限列表之后会详细介绍:
$authList
=
$this
->getAuthList(
$uid
,
$type
);
此次需要验证的规则列表转换成数组:
if
(
is_string
(
$name
)) {
$name
=
strtolower
(
$name
);
if
(
strpos
(
$name
,
','
) !== false) {
$name
=
explode
(
','
,
$name
);
}
else
{
$name
=
array
(
$name
);
}
}
所以$name参数是不区分大小写的,最终都会转换成小写
开启url模式时全部转换为小写:
if
(
$mode
==
'url'
) {
$REQUEST
= unserialize(
strtolower
(serialize(
$_REQUEST
)));
}
权限校验核心代码段之一,即循环所有该用户权限 判断 当前需要验证的权限 是否 在用户授权列表中:
foreach
(
$authList
as
$auth
) {
$query
= preg_replace(
'/^.+\?/U'
,
''
,
$auth
);
//获取url参数
if
(
$mode
==
'url'
&&
$query
!=
$auth
) {
parse_str
(
$query
,
$param
);
//获取数组形式url参数
$intersect
=
array_intersect_assoc
(
$REQUEST
,
$param
);
$auth
= preg_replace(
'/\?.*$/U'
,
''
,
$auth
);
//获取访问的url文件
if
(in_array(
$auth
,
$name
) &&
$intersect
==
$param
) {
//如果节点相符且url参数满足
$list
[] =
$auth
;
}
}
else
if
(in_array(
$auth
,
$name
)) {
$list
[] =
$auth
;
}
}
in_array($auth, $name) 如果 权限列表中 其中一条权限 等于 当前需要校验的权限 则加入到$list中
注:
$list
=
array
();
//保存验证通过的规则名
if
(
$relation
==
'or'
and
!
empty
(
$list
)) {
return
true;
}
$diff
=
array_diff
(
$name
,
$list
);
if
(
$relation
==
'and'
and
empty
(
$diff
)) {
return
true;
}
$relation
==
'or'
and
!
empty
(
$list
);
//当or时 只要有一条是通过的 则 权限为真
$relation
==
'and'
and
empty
(
$diff
);
//当and时 $name与$list完全相等时 权限为真
3、获取权限列表:
$authList
=
$this
->getAuthList(
$uid
,
$type
);
//获取用户需要验证的所有有效规则列表
这个主要流程:
获取用户组
$groups
=
$this
->getGroups(
$uid
);
//SELECT `rules` FROM think_auth_group_access a INNER JOIN think_auth_group g on a.group_id=g.id WHERE ( a.uid='1' and g.status='1' )
简化操作就是:
SELECT
`rules`
FROM
think_auth_group
WHERE
STATUS =
'1'
AND
id=
'1'
//按正常流程 去think_auth_group_access表中内联有点多余....!
取得用户组rules规则字段 这个字段中保存的是think_auth_rule规则表的id用,分割
$ids就是$groups变量最终转换成的 id数组:
$map
=
array
(
'id'
=>
array
(
'in'
,
$ids
),
'type'
=>
$type
,
'status'
=> 1,
);
取得think_auth_rule表中的规则信息,之后循环:
foreach
(
$rules
as
$rule
) {
if
(!
empty
(
$rule
[
'condition'
])) {
//根据condition进行验证
$user
=
$this
->getUserInfo(
$uid
);
//获取用户信息,一维数组
$command
= preg_replace(
'/\{(\w*?)\}/'
,
'$user[\'\\1\']'
,
$rule
[
'condition'
]);
//dump($command);//debug
@(
eval
(
'$condition=('
.
$command
.
');'
));
if
(
$condition
) {
$authList
[] =
strtolower
(
$rule
[
'name'
]);
}
}
else
{
//只要存在就记录
$authList
[] =
strtolower
(
$rule
[
'name'
]);
}
}
if
(!
empty
(
$rule
[
'condition'
])) {
//根据condition进行验证
这里就可以明白getUserInfo 会去获取配置文件AUTH_USER对应表名 去查找用户信息
重点是:
$command
= preg_replace(
'/\{(\w*?)\}/'
,
'$user[\'\\1\']'
,
$rule
[
'condition'
]);
@(
eval
(
'$condition=('
.
$command
.
');'
));
'/\{(\w*?)\}/ 可以看成要匹配的文字为 {字符串} 那么 {字符串} 会替换成$user['字符串']
$command =$user['字符串']
如果
$rule
[
'condition'
] =
'{age}'
;
$command
=
$user
[
'age'
]
$rule
[
'condition'
] =
'{age} > 5'
;
$command
=
$user
[
'age'
] > 10
@(
eval
(
'$condition=('
.
$command
.
');'
));
即:
$condition
=(
$user
[
'age'
] > 10);
这时再看下面代码 如果为真则加为授权列表
if
(
$condition
) {
$authList
[] =
strtolower
(
$rule
[
'name'
]);
}
更多关于thinkPHP相关内容感兴趣的读者可查看本站专题:《ThinkPHP入门教程》、《thinkPHP模板操作技巧总结》、《ThinkPHP常用方法总结》、《smarty模板入门基础教程》及《PHP模板技术总结》。
希望本文所述对大家基于ThinkPHP框架的PHP程序设计有所帮助。
- ThinkPHP权限认证Auth实例详解
- thinkphp Auth 权限认证
- thinkphp的 Auth权限认证
- Thinkphp 3.2 下的auth权限认证
- thinkphp auth认证表
- Thinkphp5 Auth权限认证
- Thinkphp5 Auth权限认证
- Auth权限控制的实例代码演示(thinkphp)
- (thinkPHP) 比RBAC更好的权限认证方式(Auth类认证)
- ThinkPHP之比RBAC更好用的权限管理 auth认证
- thinkphp中Auth权限类的使用
- onethink的auth权限认证解读
- rbac与auth权限认证的区别
- 一个base auth认证的实例
- HttpClient BA认证 basic auth 实例
- Django权限系统auth模块详解 转自:原文出处 auth模块是Django提供的标准权限管理系统,可以提供用户身份认证, 用户组和权限管理。 auth可以和admin模块配合使用, 快速建
- auth权限
- Auth权限
- find命令;selinux防火墙
- 1-7监控和管理linux进程
- java入门基础
- HashMap(jdk1.8)
- java 编写程序实现从控制台接收一个 5 位以上的整数,使用数组来判断该数字 * 是否是回文数。(例如:789987,12344321是回文数)
- ThinkPHP权限认证Auth实例详解
- Linux的Socket编程
- asasasa
- activiti学习笔记(四) 配置器
- 8.6 二叉树----基本操作
- 【OpenCv应用笔记】基于OpenCv的视频截图C++程序
- Struts2的系统架构
- Andrew Ng机器学习笔记1
- 浅谈Java设计模式——单实例、简单工厂、抽象工厂、观察者