tp5权限管理 附源码

源码下载:https://download.csdn.net/download/qq_14940627/11107673

首先创建一张包含URL的一张action表:

CREATE TABLE `action` (
  `action_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `action_url` varchar(255) NOT NULL DEFAULT '0' COMMENT '功能URL',
  `action_name` varchar(255) NOT NULL DEFAULT '0' COMMENT '功能名称',
  `action_desc` varchar(255) DEFAULT NULL COMMENT '功能描述',
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '-1:已删除, 0:禁止访问, 1:正常访问',
  `pid` int(11) NOT NULL DEFAULT '0' COMMENT '功能父级id',
  `module` varchar(255) DEFAULT NULL COMMENT '模块',
  `type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '功能类型:1-菜单  2-页面  3-按钮',
  `icon` varchar(255) DEFAULT NULL COMMENT '功能icon图标',
  `level` int(10) unsigned DEFAULT NULL COMMENT '功能等级',
  `group_id` int(10) unsigned DEFAULT NULL COMMENT '功能组id',
  `sort` tinyint(2) DEFAULT NULL,
  `delete_time` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`action_id`)
) ENGINE=MyISAM AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;

数据如下,大家可以根据自己实际情况插入:

INSERT INTO `action` VALUES ('2', 'admin/news/index', '新闻列表', null, '1', '0', 'admin', '0', null, null, null, '1', null);
INSERT INTO `action` VALUES ('3', 'admin/news/add', '新闻添加', null, '1', '2', 'admin', '0', null, null, null, '2', null);
INSERT INTO `action` VALUES ('4', 'admin/news/edit', '新闻编辑', null, '1', '2', 'admin', '0', null, null, null, '3', null);
INSERT INTO `action` VALUES ('5', 'admin/news/del', '新闻删除', null, '1', '2', 'admin', '0', null, null, null, '4', null);
INSERT INTO `action` VALUES ('6', 'admin/auth/index', '权限组列表', null, '1', '0', 'admin', '0', null, null, null, '5', null);
INSERT INTO `action` VALUES ('7', 'admin/auth/edit', '权限编辑', null, '1', '6', 'admin', '0', null, null, null, '6', null);
INSERT INTO `action` VALUES ('8', 'admin/auth/add', '添加权限组', null, '1', '6', 'admin', '0', null, null, null, '7', null);
INSERT INTO `action` VALUES ('9', 'admin/auth/del', '权限删除', null, '1', '6', 'admin', '0', null, null, null, '8', null);
INSERT INTO `action` VALUES ('10', 'admin/manager/index', '管理员列表', null, '1', '0', null, '0', null, null, null, null, null);
INSERT INTO `action` VALUES ('11', 'admin/manager/add', '添加管理员', null, '1', '10', null, '0', null, null, null, null, null);
INSERT INTO `action` VALUES ('12', 'admin/manager/edit', '编辑管理员', null, '1', '10', null, '0', null, null, null, null, null);
INSERT INTO `action` VALUES ('13', 'admin/manager/del', '删除管理员', null, '1', '10', null, '0', null, null, null, null, null);
INSERT INTO `action` VALUES ('14', 'admin/login/pwdmodify', '修改密码', null, '1', '0', null, '0', null, null, null, null, null);
INSERT INTO `action` VALUES ('15', 'admin/column/index', '栏目管理', null, '1', '0', null, '0', null, null, null, null, null);
INSERT INTO `action` VALUES ('16', 'admin/column/add', '增加栏目', null, '1', '15', null, '0', null, null, null, null, null);
INSERT INTO `action` VALUES ('17', 'admin/column/edit', '编辑栏目', null, '1', '15', null, '0', null, null, null, null, null);
INSERT INTO `action` VALUES ('18', 'admin/column/del', '删除栏目', null, '1', '15', null, '0', null, null, null, null, null);

创建一张管理员的表

CREATE TABLE `admin` (
  `admin_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `admin_name` varchar(32) NOT NULL,
  `pwd` varchar(255) NOT NULL,
  `su_pwd` varchar(255) DEFAULT NULL,
  `nicke_name` varchar(255) DEFAULT NULL,
  `login_time` int(11) DEFAULT NULL,
  `admin_status` tinyint(4) DEFAULT '1' COMMENT '管理员状态: -1: 删除   0: 禁用   1:正常',
  `admin_sign` tinyint(1) NOT NULL COMMENT '1- 超级管理员,2-一般管理员',
  `create_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建者ID',
  `create_time` int(11) DEFAULT NULL COMMENT '创建时间',
  `update_time` int(11) DEFAULT NULL COMMENT '跟新时间',
  `sort` smallint(6) NOT NULL DEFAULT '99',
  PRIMARY KEY (`admin_id`)
) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

创建一张角色表

CREATE TABLE `role` (
  `role_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `role_name` varchar(255) NOT NULL,
  `role_desc` varchar(255) DEFAULT NULL COMMENT '角色描述',
  `role_pid` int(11) NOT NULL DEFAULT '0',
  `role_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '-1:删除 , 0:禁用,1正常',
  `role_path` varchar(255) DEFAULT NULL COMMENT '树路径',
  `admin_sign` varchar(255) DEFAULT NULL,
  `create_time` int(11) DEFAULT NULL,
  `update_time` int(11) DEFAULT NULL,
  PRIMARY KEY (`role_id`)
) ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;

最后创建一张管理员和角色对应的表

CREATE TABLE `admin_role` (
  `admin_id` int(10) unsigned NOT NULL DEFAULT '0',
  `role_id` int(11) NOT NULL DEFAULT '0',
  `create_time` int(11) DEFAULT NULL,
  PRIMARY KEY (`admin_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

创建一个钩子在action之前执行

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------

// 应用行为扩展定义文件
return [
    // 应用初始化
    'app_init'     => [],
    // 应用开始
    'app_begin'    => [],
    // 模块初始化
    'module_init'  => [],
    // 操作开始执行
    'action_begin' => ['app\\behavior\\OperateBehavior'],
    // 视图内容过滤
    'view_filter'  => [],
    // 日志写入
    'log_write'    => [],
    // 应用结束
    'app_end'      => [],
];

不要忘记在common.php 中把钩子加上去

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <[email protected]>
// +----------------------------------------------------------------------

// 应用公共文件
use think\Hook;

Hook::add('action_begin','app\\behavior\\OperateBehavior');

然后开始具体的behavior:OperateBehavior.php

tp5权限管理 附源码

把所有的权限存储在Session中再来判断,当前的访问路径是否有权限

<?php

namespace app\behavior;

use think\Controller;
use think\Exception;
use think\Session;

class OperateBehavior extends Controller{

    // 定义需要排除的权限路由
    protected $exclude = [
        'index/index/index',
        'admin/login/index',
        'admin/index/index',
        'admin/class/getclass',
        'admin/login/loginverify',
        'admin/login/outlogin',
        'admin/index/info',
        'admin/class/getclass'
    ];

    /**
     * 权限验证
     */
    public function run(&$params){


        // 行为逻辑
        try {
            // 获取当前访问路由
            $url  = $this->getActionUrl();

            if(empty(Session::get()) && !in_array($url,$this->exclude)){
                $this->error('请先登录','/admin/login');
            }

            // 用户所拥有的权限路由
            $auth = Session::get('auth.url') ? Session::get('auth.url'): [];

            if(!in_array($url, $auth) && !in_array($url, $this->exclude)){
                $this->error('无权限访问');
            }


        } catch (Exception $ex) {
            print_r($ex);
        }
    }

    /**
     * 获取当前访问路由
     * @param $Request
     * @return string
     */
    private function getActionUrl()
    {
        $module     = request()->module();
        $controller = request()->controller();
        $action     = request()->action();
        $url        = $module.'/'.$controller.'/'.$action;
        return strtolower($url);
    }



}

登录验证判断权限

<?php


namespace app\admin\controller;

use app\admin\model\AdminModel;
use think\Controller;
use think\Log;
use think\Request;
use think\response\Json;
use think\Session;

class LoginController extends Controller{

    public function index(){

        return $this->fetch();
    }


    /**
     * 登录验证
     * @param Request $Request
     * @return Json
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function loginVerify(Request $Request)
    {

        $name= input('post.name');
        $pwd= input('post.pwd');

        if(!$name) return json(array('code'=>0,'msg'=>'用户名不能为空'));
        if(!$pwd)  return json(array('code'=>0,'msg'=>'密码不能为空'));
        $info = (new AdminModel)->loginVerify($name, $pwd);  // 调用 AdminModel 中的 loginVerify() 验证方法

        if(false === $info) return json(array('code'=>0,'msg'=>'登录错误!'));
        if(-2 === $info)    return json(array('code'=>-2,'msg'=>'账号不存在'));
        if( 0 === $info)    return json(array('code'=>0,'msg'=>'账号被禁用'));
        if(-1 === $info)    return json(array('code'=>-1,'msg'=>'账号被删除'));
        if(-3 === $info)    return json(array('code'=>-3,'msg'=>'密码不正确'));
        if($info)
            Log::record('login:登录成功','operate');
        return json(array('code'=>1,'url'=>'/admin/index','msg'=>'登录成功!'));
    }

    public function outlogin(){

        Session::clear();
        $this->redirect('/admin/login');
    }

    public function pwdModify(){

        $admin_info= Session::get('user_info');

        if (Request::instance()->isPost()) {

            $oldpwd= trim(input('post.oldpwd'));
            $newpwd= trim(input('post.newpwd'));

            $admin = AdminModel::adminFindById($admin_info['admin_id']);
            if(md5($oldpwd) != $admin->pwd){
                $this->error('原始密码错误');
            }else{
                AdminModel::editAdmin($admin_info['admin_id'], ['pwd'=>md5($newpwd)]);

                $this->success('修改成功');
            }
        }

        $this->assign('admin', $admin_info);

        return $this->fetch();
    }

}

在AdminModel 中进行权限的判断存储

<?php
namespace app\admin\model;
use think\Model;

use think\Db;
use think\Session;

class AdminModel extends Model
{
    protected $table = '';
    protected $pk    = 'admin_id';


    public static function AdminList($size=5){

        return self::where('admin_status', '1')
            ->where('admin_id','<>', 1)->order('sort asc')->paginate($size);

    }

    public static function addAdmin($admin_data){
        return self::create($admin_data);
    }

    public static function editAdmin($admin_id, $admin_data){

        return self::where('admin_id', $admin_id)->update($admin_data);
    }

    public static function adminFindById($admin_id){
        return self::where('admin_id', $admin_id)->find();
    }

    public static function delAdmin($admin_id){
        return self::where('admin_id', $admin_id)->update(['admin_status'=>-1]);
    }


    /**
     * 登录验证
     * @param $name
     * @param $pwd
     * @return bool|int
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\Exception
     */
    public function loginVerify($name, $pwd){
        if(!$name) return false;
        if(!$pwd)  return false;

        // 定义存session时 需要删除的个人信息
        $unField  = ['pwd','create_time','update_time'];

        $userInfo = self::where('admin_name','=', $name)->find();

        if(!$userInfo)                    return -2;//账号不存在
        if(-1 == $userInfo->admin_status) return -1;//账号被删除
        if( 0 == $userInfo->admin_status) return  0;//账号被禁用

        // 密码、超码 验证
        if($userInfo->pwd != md5($pwd)) return -3;//密码不正确

        // admin_sign:管理员标记,1 超级管理员,2 一般管理员
        if(1 == $userInfo->admin_sign) {
            //获取超级管理员权限
            $auth = $this->_getAdminAuth();
        }else{
            //获取普通管理员权限
            $auth = $this->_getAuth($userInfo->admin_id);
        }

        // 删除部分个人信息
        foreach ($unField as $fKey => $fVal){
            unset($userInfo[$fVal]);
        }


        $data['login_time'] = time();

        // 更新登录状态
        self::where('admin_id', $userInfo->admin_id)->update($data);

        // 获取用户管理员角色名称
        $roleName = $this->getUserRoleName($userInfo->admin_id);
        $userInfo['roleName'] = $roleName;

        // session存储个人信息
        Session::set('user_info', $userInfo->toArray());
        // session存储权限
        Session::set('auth', $auth);


        return true;
    }

    /**
     * 获取管理员角色名称
     * @param $adminId
     * @return array|null|\PDOStatement|string|Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getUserRoleName($adminId){
        if(!is_numeric($adminId)) return '';
        $roleNameArr = $this
            ->alias('a')
            ->join('admin_role ar', 'a.admin_id=ar.admin_id', 'LEFT')
            ->join('role r', 'ar.role_id=r.role_id', 'LEFT')
            ->where('a.admin_id',$adminId)
            ->field('r.role_name, r.role_id')
            ->find();
        $roleName = empty($roleNameArr['role_name'])?'':$roleNameArr['role_name'];
        return $roleName;
    }

    /**
     * 获取超级管理员admin权限
     * @return array
     */
    private function _getAdminAuth(){
        $action = ActionModel::where('status',1)->select();
        if($action) {

            $action  = $action->toArray();  // 权限方法数组 $action
            $menuUrl = $this->_getMenuUrl($action);
        }
        unset($action);
        return $menuUrl ? $menuUrl : [];
    }


    /**
     * 获取普通管理员权限
     * @param $userId
     * @return array|bool
     */
    private function _getAuth($userId)
    {

        // 管理员角色权限
        $roAction = Db::name('admin_role')->alias('ar')
            ->join('role_action ra', 'ra.role_id=ar.role_id', 'LEFT')
            ->join('action a', 'a.action_id=ra.action_id', 'LEFT')
            ->where('ar.admin_id',$userId)
            ->where('a.status',1)
            ->order('a.sort')
            ->field('a.*')
            ->select()->toArray();





        $menuUrl= [];
        if( $roAction ) {
            $menuUrl = $this->_getMenuUrl( $roAction );
        }

        return $menuUrl ? $menuUrl : [];
    }


    /**
     * 获取菜单树和url列表
     * @param array $action
     * @return array|bool
     */
    private function _getMenuUrl(array $action){
        if(empty($action)) return false;
        $menu  = [];   // 主菜单数组
        $sort  = [];   // 主菜单排序数组
        $url   = [];   // 权限url数组

        foreach ($action as $aKey => $aVal) {
            if(1 == $aVal['type'] && !$aVal['module']){  // type=1\module=0 :主菜单 (ps:主菜单是通过点击'添加action'写入action表的)
                $sort[]  = $aVal['sort'];   // 排序
                $menu[] = $aVal;            // 主菜单数组
            }
            $url[] = strtolower($aVal['action_url']);   // 权限url数组
        }

        $menu=$this->_treeNode( $action);

        // $menu 跟随 $sort 升序排序
//        array_multisort($sort, SORT_ASC, $menu);

       /* foreach ($menu as $mKey => $mVal){
            $menu[$mKey]['action_url'] = 'javascript:;';
            $menu[$mKey]['first'] = 1;
        }*/

        return array('menu'=>$menu,'url'=>$url);
    }


    private function _treeNode($data,$parentId = 0)
    {
        // 用于保存整理好的分类节点
        $node = [];
        // 循环所有分类
        foreach ($data as $key => $value) {
            // 如果当前分类的父id等于要寻找的父id则写入$node数组,并寻找当前分类id下的所有子分类
            if($parentId == $value ['pid']) {
                $node [$key] = $value;
                $node [$key] ['child'] = $this->_treeNode($data,$value ['action_id']);
            }
        }
        return $node;
    }

}

至此一个权限基本完成,效果如下:

tp5权限管理 附源码

tp5权限管理 附源码tp5权限管理 附源码tp5权限管理 附源码