天天看点

Auth权限管理

1. 简介

Auth权限管理比RBAC更加灵活,auth对权限的控制更为精细。

Auth的特性:

  • 是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。 auth=newAuth(); auth->check(‘规则名称’,’用户id’)
  • 可以同时对多条规则进行认证,并设置多条规则的关系(or或者and)。 auth=newAuth(); auth->check(‘规则1,规则2’,’用户id’,’and’)
  • 一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组),我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组的权限)。
  • 支持规则表达式。在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>50 and {score}<100 表示用户的分数在50-100之间时这条规则才会通过。

2. 基本用法

以ThinkPHP3.2.3为例,进行简单介绍。

Auth类文件为ThinkPHP\Library\Think\Auth.class.php,默认的认证方式为实时认证。

建立四张数据表。

# 用户表
CREATE TABLE IF NOT EXISTS `think_user` (
  `uid` mediumint() unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `username` varchar() NOT NULL DEFAULT '' COMMENT '用户名',
  `password` char() NOT NULL DEFAULT '' COMMENT '密码',
  `status` tinyint() unsigned NOT NULL DEFAULT  COMMENT '状态:0禁用,1正常',
  `score` mediumint() unsigned NOT NULL DEFAULT  COMMENT '积分',
  `login_time` int() unsigned NOT NULL DEFAULT  COMMENT '最近一次登录时间',
  `login_ip` int() NOT NULL DEFAULT '0' COMMENT '最近一次登录ip',
  PRIMARY KEY (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='用户表';

# 用户-用户组关系表
CREATE TABLE IF NOT EXISTS `think_auth_group_access` (  
    `uid` mediumint() unsigned NOT NULL DEFAULT  COMMENT '用户id',  
    `group_id` mediumint() unsigned NOT NULL DEFAULT  COMMENT '组id', 
    UNIQUE KEY `uid_group_id` (`uid`,`group_id`),  
    KEY `uid` (`uid`), 
    KEY `group_id` (`group_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='用户-用户组关系表';

# 规则表
CREATE TABLE IF NOT EXISTS `think_auth_rule` (  
    `id` mediumint() unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',  
    `name` char() NOT NULL DEFAULT '' COMMENT '规则的唯一标识(英文)',  
    `title` char() NOT NULL DEFAULT '' COMMENT '规则的中文名称',  
    `type` tinyint() NOT NULL DEFAULT '1',    
    `status` tinyint() NOT NULL DEFAULT '1' COMMENT '状态:1正常,0禁用',  
    `condition` char() NOT NULL DEFAULT '' COMMENT '规则的附加条件',  
    PRIMARY KEY (`id`),  
    UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='规则表';

# 用户组表
CREATE TABLE IF NOT EXISTS `think_auth_group` ( 
    `id` mediumint() unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', 
    `title` char() NOT NULL DEFAULT '' COMMENT '用户组的中文名称', 
    `status` tinyint() NOT NULL DEFAULT '1' COMMENT '状态:0禁用,1正常', 
    `rules` char() NOT NULL DEFAULT '' COMMENT '用户组拥有的规则id, 多个规则用,隔开', 
    PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT '用户组表';
           

模块配置文件D:\xampp\htdocs\test\Application\Adm\Conf\config.php的代码如下:

<?php
return array(
    //'配置项'=>'配置值'

    // 数据库配置
    'DB_TYPE'               =>  'mysql',        // 数据库类型
    'DB_HOST'               =>  '127.0.0.1',    // 服务器地址
    'DB_NAME'               =>  'auth',         // 数据库名
    'DB_USER'               =>  'root',     // 用户名
    'DB_PWD'                =>  '123456',   // 密码
    'DB_PORT'               =>  '3306',     // 端口
    'DB_PREFIX'             =>  'think_',   // 数据库表前缀

    // auth权限验证的配置
    'AUTH_CONFIG' => array(
            'AUTH_ON'           => true,                // 认证开关
            'AUTH_TYPE'         => ,                   // 认证方式:1为实时认证,2为登录认证。
            'AUTH_GROUP'        => 'think_auth_group',        // 用户组表
            'AUTH_GROUP_ACCESS' => 'think_auth_group_access', // 用户-用户组关系表
            'AUTH_RULE'         => 'think_auth_rule',         // 权限规则表
            'AUTH_USER'         => 'think_user',              // 用户表
    ),
);
           

测试数据如下:

用户表(think_user):

uid username password status score login_time login_ip
1 admin e10adc3949ba59abbe56e057f20f883e 1
2 user01 e10adc3949ba59abbe56e057f20f883e 1
3 user02 e10adc3949ba59abbe56e057f20f883e 1 60 1497321747 2130706433

规则表(think_auth_rule):

id name title type status condition
1 adm/index/index 后台首页 1 1
2 adm/index/test 测试页面 1 1 {score}>50 and {score}<100

用户组表(think_auth_group)

id title status rules
1 普通会员 1 1
2 黄金会员 1 1,2

用户-用户组关系表(think_auth_group_access)

uid group_id
2 1
3 2

D:\xampp\htdocs\test\Application\Adm\Controller\PublicController.class.php的代码如下:

<?php
namespace Adm\Controller;
use Think\Controller;

class PublicController extends Controller {

    /**
     * 用户登录页面
     * http://127.0.0.1/test/index.php/public/login
     */
    public function login() {
        $this->display();
    }

    /**
     * 登录提交的地址
     */
    public function login_submit() {
        if(!IS_POST) $this->error('页面不存在,请稍后再试', U('Public/login'));

        $username = I('username','');
        $password = I('password','');

        $user_info = M('user')->where("username = '$username' AND password = '".md5($password)."'")->find();

        if(!$user_info) $this->error('用户名或密码错误', U('Public/login'));

        if(!$user_info['status']) $this->error('该用户已被禁用,暂时不可登录', U('Public/login'));

        // 更新登录信息
        M('user')->save(array("uid"=> $user_info["uid"], "login_time"=> time(), "login_ip" => ip2long(get_client_ip())));

        // 写入session
        session('uid', $user_info['uid']);   // 用户id(uid)
        session('username', $user_info['username']);   // 用户名

        $this->success('登录成功', U('Index/index'));
    }
}
           

D:\xampp\htdocs\test\Application\Adm\Controller\CommonController.class.php的代码如下:

<?php
namespace Adm\Controller;
use Think\Controller;

/**
 * @author Administrator
 * 所有需要进行权限验证的控制器,使其继承CommonController即可
 */
class CommonController extends Controller {

    /**
     * ThinkPHP中提供了_initialize()方法,在类初始化时,_initialize()方法会自动执行
     */
    protected function _initialize() {

        // 实例化auth对象
        $auth = new \Think\Auth();
        $rule_name = strtolower(MODULE_NAME.'/'.CONTROLLER_NAME.'/'.ACTION_NAME);

        // 验证权限
        $res = $auth->check($rule_name, $_SESSION['uid']);
        if($res === false) $this->error('您没有权限访问!', U('Public/login'));
    }
}
           

D:\xampp\htdocs\test\Application\Adm\Controller\IndexController.class.php的代码如下:

<?php
namespace Adm\Controller;

/**
 * @author Administrator
 * 需要进行auth权限验证的控制器就继承CommonController
 */
class IndexController extends CommonController {

    /**
     * 后台首页
     * http://127.0.0.1/test/index.php/index/index
     */
    public function index() {
        dump(session());
        echo '后台首页!';
    }

    /**
     * 测试页面
     * http://127.0.0.1/test/index.php/index/test
     */
    public function test() {
        echo MODULE_NAME.'<br/>';
        echo CONTROLLER_NAME.'<br/>';
        echo ACTION_NAME.'<br/>';
        echo '这是测试页面';
    }

}
           

继续阅读