Home Backend Development PHP Tutorial ThinkPHP权限认证Auth实例详解_PHP

ThinkPHP权限认证Auth实例详解_PHP

Jun 01, 2016 am 11:50 AM
auth thinkphp Authority authentication

本文以实例代码的形式深入剖析了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');

Copy after login

配置文件Application\Common\Conf\config.php部分:

<&#63;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'//用户信息表
  )
);

Copy after login

项目Home控制器部分Application\Home\Controller\IndexController.class.php代码:

<&#63;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('认证:失败');
    }
  }
}
Copy after login

以上这些代码就是最基本的验证代码示例。

下面是源码阅读:

1、权限检验类初始化配置信息:

$Auth = new \Think\Auth();
Copy after login

创建一个对象时程序会合并配置信息
程序会合并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'));
    }
  }

Copy after login

2、检查权限:

check($name, $uid, $type = 1, $mode = 'url', $relation = 'or')
Copy after login

大体分析一下这个方法

首先判断是否关闭权限校验 如果配置信息AUTH_ON=>false 则不会进行权限验证 否则继续验证权限

if (!$this->_config['AUTH_ON']) {
  return true;
}
Copy after login

获取权限列表之后会详细介绍:

$authList = $this->getAuthList($uid, $type);

Copy after login

此次需要验证的规则列表转换成数组:

if (is_string($name)) {
  $name = strtolower($name);
  if (strpos($name, ',') !== false) {
 $name = explode(',', $name);
  } else {
 $name = array($name);
  }
}

Copy after login

所以$name参数是不区分大小写的,最终都会转换成小写


开启url模式时全部转换为小写:

if ($mode == 'url') {
  $REQUEST = unserialize(strtolower(serialize($_REQUEST)));
}

Copy after login

权限校验核心代码段之一,即循环所有该用户权限 判断 当前需要验证的权限 是否 在用户授权列表中:

foreach ($authList as $auth) {
  $query = preg_replace('/^.+\&#63;/U', '', $auth);//获取url参数
  if ($mode == 'url' && $query != $auth) {
 parse_str($query, $param); //获取数组形式url参数
 $intersect = array_intersect_assoc($REQUEST, $param);
 $auth = preg_replace('/\&#63;.*$/U', '', $auth);//获取访问的url文件
 if (in_array($auth, $name) && $intersect == $param) { //如果节点相符且url参数满足
   $list[] = $auth;
 }
  } else if (in_array($auth, $name)) {
 $list[] = $auth;
  }
}

Copy after login

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完全相等时 权限为真

Copy after login

3、获取权限列表:

$authList = $this->getAuthList($uid, $type); //获取用户需要验证的所有有效规则列表

Copy after login

这个主要流程:

获取用户组

$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' )

Copy after login

简化操作就是:

SELECT `rules` FROM think_auth_group WHERE STATUS = '1' AND id='1'//按正常流程 去think_auth_group_access表中内联有点多余....!

Copy after login

取得用户组rules规则字段 这个字段中保存的是think_auth_rule规则表的id用,分割

$ids就是$groups变量最终转换成的 id数组:

$map = array(
  'id' => array('in', $ids),
  'type' => $type,
  'status' => 1,
);

Copy after login

取得think_auth_rule表中的规则信息,之后循环:

foreach ($rules as $rule) {
   if (!empty($rule['condition'])) { //根据condition进行验证
    $user = $this->getUserInfo($uid); //获取用户信息,一维数组
    $command = preg_replace('/\{(\w*&#63;)\}/', '$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进行验证

Copy after login

这里就可以明白getUserInfo 会去获取配置文件AUTH_USER对应表名 去查找用户信息

重点是:

$command = preg_replace('/\{(\w*&#63;)\}/', '$user[\'\\1\']', $rule['condition']);
@(eval('$condition=(' . $command . ');'));
Copy after login

'/\{(\w*?)\}/ 可以看成要匹配的文字为 {字符串} 那么 {字符串} 会替换成$user['字符串']
$command =$user['字符串']

如果

$rule['condition'] = '{age}';
$command =$user['age']
$rule['condition'] = '{age} > 5';
$command =$user['age'] > 10
@(eval('$condition=(' . $command . ');'));
Copy after login

即:

$condition=($user['age'] > 10);

Copy after login

这时再看下面代码 如果为真则加为授权列表

if ($condition) {
   $authList[] = strtolower($rule['name']);
}
Copy after login

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to run thinkphp project How to run thinkphp project Apr 09, 2024 pm 05:33 PM

To run the ThinkPHP project, you need to: install Composer; use Composer to create the project; enter the project directory and execute php bin/console serve; visit http://localhost:8000 to view the welcome page.

There are several versions of thinkphp There are several versions of thinkphp Apr 09, 2024 pm 06:09 PM

ThinkPHP has multiple versions designed for different PHP versions. Major versions include 3.2, 5.0, 5.1, and 6.0, while minor versions are used to fix bugs and provide new features. The latest stable version is ThinkPHP 6.0.16. When choosing a version, consider the PHP version, feature requirements, and community support. It is recommended to use the latest stable version for best performance and support.

How to run thinkphp How to run thinkphp Apr 09, 2024 pm 05:39 PM

Steps to run ThinkPHP Framework locally: Download and unzip ThinkPHP Framework to a local directory. Create a virtual host (optional) pointing to the ThinkPHP root directory. Configure database connection parameters. Start the web server. Initialize the ThinkPHP application. Access the ThinkPHP application URL and run it.

Which one is better, laravel or thinkphp? Which one is better, laravel or thinkphp? Apr 09, 2024 pm 03:18 PM

Performance comparison of Laravel and ThinkPHP frameworks: ThinkPHP generally performs better than Laravel, focusing on optimization and caching. Laravel performs well, but for complex applications, ThinkPHP may be a better fit.

How to install thinkphp How to install thinkphp Apr 09, 2024 pm 05:42 PM

ThinkPHP installation steps: Prepare PHP, Composer, and MySQL environments. Create projects using Composer. Install the ThinkPHP framework and dependencies. Configure database connection. Generate application code. Launch the application and visit http://localhost:8000.

Development suggestions: How to use the ThinkPHP framework to implement asynchronous tasks Development suggestions: How to use the ThinkPHP framework to implement asynchronous tasks Nov 22, 2023 pm 12:01 PM

"Development Suggestions: How to Use the ThinkPHP Framework to Implement Asynchronous Tasks" With the rapid development of Internet technology, Web applications have increasingly higher requirements for handling a large number of concurrent requests and complex business logic. In order to improve system performance and user experience, developers often consider using asynchronous tasks to perform some time-consuming operations, such as sending emails, processing file uploads, generating reports, etc. In the field of PHP, the ThinkPHP framework, as a popular development framework, provides some convenient ways to implement asynchronous tasks.

How is the performance of thinkphp? How is the performance of thinkphp? Apr 09, 2024 pm 05:24 PM

ThinkPHP is a high-performance PHP framework with advantages such as caching mechanism, code optimization, parallel processing and database optimization. Official performance tests show that it can handle more than 10,000 requests per second and is widely used in large-scale websites and enterprise systems such as JD.com and Ctrip in actual applications.

ThinkPHP6 backend management system development: realizing backend functions ThinkPHP6 backend management system development: realizing backend functions Aug 27, 2023 am 11:55 AM

ThinkPHP6 backend management system development: Implementing backend functions Introduction: With the continuous development of Internet technology and market demand, more and more enterprises and organizations need an efficient, safe, and flexible backend management system to manage business data and conduct operational management. This article will use the ThinkPHP6 framework to demonstrate through examples how to develop a simple but practical backend management system, including basic functions such as permission control, data addition, deletion, modification and query. Environment preparation Before starting, we need to install PHP, MySQL, Com

See all articles