您现在的位置是:网站首页 > 脚本编程>
thinkphp5 auth 权限认证及用法
简介
本人一直使用tp3.2.3版本,因为用的比较习惯,新的项目公司要求用tp5版本。一开始用tp5版本还有些不习惯。因为tp5版本不想3.2.3基类那么多,tp5版本需要使用composer来安装扩展类,通过composer安装了一个auth权限验证的类,使用的时候各种报错。各种折腾还是报错,无奈还是自己按照tp3.2.3整理出来一个auth类。
本人一直使用tp3.2.3版本,因为用的比较习惯,新的项目公司要求用tp5版本。一开始用tp5版本还有些不习惯。因为tp5版本不想3.2.3基类那么多,tp5版本需要使用composer来安装扩展类,通过composer安装了一个auth权限验证的类,使用的时候各种报错。各种折腾还是报错,无奈还是自己按照tp3.2.3整理出来一个auth类。
/** * 权限认证类 * 功能特性: * 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。 * $auth=new Auth(); $auth->check('规则名称','用户id') * 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and) * $auth=new Auth(); $auth->check('规则1,规则2','用户id','and') * 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or * 3,一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组权限) * * 4,支持规则表达式。 * 在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。 */
//数据库 /* -- ---------------------------- -- think_auth_rule,规则表, -- id:主键,name:规则唯一标识, title:规则中文名称 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证 -- ---------------------------- 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 '', `title` char(20) NOT NULL DEFAULT '', `type` tinyint(1) NOT NULL DEFAULT '1', `status` tinyint(1) NOT NULL DEFAULT '1', `condition` char(100) NOT NULL DEFAULT '', # 规则附件条件,满足附加条件的规则,才认为是有效的规则 PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- ---------------------------- -- think_auth_group 用户组表, -- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用 -- ---------------------------- 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 DEFAULT CHARSET=utf8; -- ---------------------------- -- think_auth_group_access 用户组明细表 -- uid:用户id,group_id:用户组id -- ---------------------------- DROP TABLE IF EXISTS `think_auth_group_access`; CREATE TABLE `think_auth_group_access` ( `uid` mediumint(8) unsigned NOT NULL, `group_id` mediumint(8) unsigned NOT NULL, UNIQUE KEY `uid_group_id` (`uid`,`group_id`), KEY `uid` (`uid`), KEY `group_id` (`group_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 用户表按照自己的需求自行创建 */
auth类
<?php namespace auth; use think\Db; use think\Config; class Auth{ //默认配置 protected $_config = array( 'AUTH_ON' => true, // 认证开关 'AUTH_TYPE' => 1, // 认证方式,1为实时认证;2为登录认证。 'AUTH_GROUP' => 'auth_group', // 用户组数据表名 'AUTH_GROUP_ACCESS' => 'auth_group_access', // 用户-用户组关系表 'AUTH_RULE' => 'auth_rule', // 权限规则表 'AUTH_USER' => 'member' // 用户信息表 ); public function __construct() { $prefix = "db_"; $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 ($auth = Config::get('auth')) { //可设置配置项 AUTH_CONFIG, 此配置项为数组。 $this->_config = array_merge($this->_config, $auth); } } /** * 检查权限 * @param name string|array 需要验证的规则列表,支持逗号分隔的权限规则或索引数组 * @param uid int 认证用户的id * @param string mode 执行check的模式 * @param relation string 如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证 * @return boolean 通过验证返回true;失败返回false */ public function check($name, $uid, $type=1, $mode='url', $relation='or') { 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); } } $list = array(); //保存验证通过的规则名 if ($mode=='url') { $REQUEST = unserialize( strtolower(serialize($_REQUEST)) ); } foreach ( $authList as $auth ) { $query = preg_replace('/^.+\?/U','',$auth); if ($mode=='url' && $query!=$auth ) { parse_str($query,$param); //解析规则中的param $intersect = array_intersect_assoc($REQUEST,$param); $auth = preg_replace('/\?.*$/U','',$auth); if ( in_array($auth,$name) && $intersect==$param ) { //如果节点相符且url参数满足 $list[] = $auth ; } }else if (in_array($auth , $name)){ $list[] = $auth ; } } if ($relation == 'or' and !empty($list)) { return true; } $diff = array_diff($name, $list); if ($relation == 'and' and empty($diff)) { return true; } return false; } /** * 根据用户id获取用户组,返回值为数组 * @param uid int 用户id * @return array 用户所属的用户组 array( * array('uid'=>'用户id','group_id'=>'用户组id','title'=>'用户组名称','rules'=>'用户组拥有的规则id,多个,号隔开'), * ...) */ public function getGroups($uid) { static $groups = array(); if (isset($groups[$uid])) return $groups[$uid]; $user_groups = Db::view($this->_config['AUTH_GROUP_ACCESS'], 'uid,group_id') ->view($this->_config['AUTH_GROUP'], 'title,rules', "{$this->_config['AUTH_GROUP_ACCESS']}.group_id={$this->_config['AUTH_GROUP']}.id", 'LEFT') ->where("{$this->_config['AUTH_GROUP_ACCESS']}.uid='{$uid}' and {$this->_config['AUTH_GROUP']}.status='1'") ->select(); $groups[$uid]=$user_groups?:array(); return $groups[$uid]; } /** * 获得权限列表 * @param integer $uid 用户id * @param integer $type */ protected function getAuthList($uid,$type) { static $_authList = array(); //保存用户验证通过的权限列表 $t = implode(',',(array)$type); if (isset($_authList[$uid.$t])) { return $_authList[$uid.$t]; } if( $this->_config['AUTH_TYPE']==2 && isset($_SESSION['_AUTH_LIST_'.$uid.$t])){ return $_SESSION['_AUTH_LIST_'.$uid.$t]; } //读取用户所属用户组 $groups = $this->getGroups($uid); $ids = array();//保存用户所属用户组设置的所有权限规则id foreach ($groups as $g) { $ids = array_merge($ids, explode(',', trim($g['rules'], ','))); } $ids = array_unique($ids); if (empty($ids)) { $_authList[$uid.$t] = array(); return array(); } $map=array( 'id'=>array('in',$ids), 'type'=>$type, 'status'=>1, ); //读取用户组所有权限规则 $rules = Db::table($this->_config['AUTH_RULE'])->where($map)->field('condition,name')->select(); //循环规则,判断结果。 $authList = array(); // 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']); } } $_authList[$uid.$t] = $authList; if($this->_config['AUTH_TYPE']==2){ //规则列表结果保存到session $_SESSION['_AUTH_LIST_'.$uid.$t]=$authList; } return array_unique($authList); } /** * 获得用户资料,根据自己的情况读取数据库 */ protected function getUserInfo($uid) { static $userinfo=array(); if(!isset($userinfo[$uid])){ $userinfo[$uid]=M()->where(array('uid'=>$uid))->table($this->_config['AUTH_USER'])->find(); } return $userinfo[$uid]; } } ?>
公共类
<?php namespace app\admin\Controller; use think\Controller; use think\Request; use auth\Auth; use think\Db; class Common extends Controller { public $loginMarked; public function _initialize() { if(!session('aid')) { $this->redirect('login/index'); } $auth = new Auth(); $request = \think\Request::instance(); $ACTION_NAME=$request->action(); $CONTROLLER_NAME=$request->controller(); if(!$auth->check( $CONTROLLER_NAME.'/'.$ACTION_NAME,session('aid')) && session('aid') != 1){ $group_ids=Db::name("auth_group_access")->where("uid=".$_SESSION['think']['aid'])->column("group_id"); if($group_ids[0]!="30") { $this->error('没有权限'); } } $admin_marked="qiblog-admin-mark"; $this->loginMarked = md5($admin_marked); $this->checkLogin(); $this->assign("menu",$this->show_menu()); } //查询菜单 public function show_menu() { $field = 'id,name,title,module'; $where['pid'] = 0;//顶级ID $where['status'] = 1;//显示状态 $where['sfxs']=1; $data = Db::name("auth_rule")->field($field)->where($where)->order("sort asc")->select(); $auth = new Auth(); //没有权限的菜单不显示 foreach ($data as $k=>$v){ if(!$auth->check($v['name'], session('aid')) && session('aid') != 1){ unset($data[$k]); }else{ // status = 1 为菜单显示状态 //查询出该会员所在的组(改造过的) if(session('aid') != 1) { $group_id=Db::name("auth_group_access")->where("uid=".$_SESSION['think']['aid'])->column("group_id"); $rule=Db::name("auth_group")->where("id=".$group_id[0])->column("rules"); $maps['id']=array('in',$rule[0]); } $maps['pid']=$v['id']; $maps['status']=1; $maps['sfxs']=1; $data[$k]['sub'] = Db::name("auth_rule")->field($field)->where($maps)->order("sort asc")->select(); $data[$k]['default_name'] = $data[$k]['sub']['0']['name']; $data[$k]['default_title'] = $data[$k]['sub']['0']['title']; foreach ($data[$k]['sub'] as $k2 => $v2){ if(!$auth->check($v2['name'], session('aid')) && session('aid') != 1){ unset($data[$k]['sub'][$k2]); } } } } return $data; } //检测是否登录 public function checkLogin() { if (isset($_COOKIE[$this->loginMarked])) { $cookie = explode("_", $_COOKIE[$this->loginMarked]); $timeout = 3600; if (time() > (end($cookie) + $timeout)) { setcookie($this->loginMarked, NULL, -3600, "/"); unset($_SESSION[$this->loginMarked], $_COOKIE[$this->loginMarked]); echo '<literal><script>top.location.href="'.U('Login/index').'";</script></literal>'; } else { if ($cookie[0] == $_SESSION[$this->loginMarked]) { setcookie("$this->loginMarked", $cookie[0] . "_" . time(), 0, "/"); } else { setcookie("$this->loginMarked", NULL, -3600, "/"); unset($_SESSION[$this->loginMarked], $_COOKIE[$this->loginMarked]); $this->error("帐号异常,请重新登录", U("Login/index")); } } } else { $this->redirect("Login/index"); } return TRUE; } } ?>
登录类
<?php namespace app\admin\controller; use think\Controller; use think\Request; use think\Db; class Login extends Controller { public $loginMarked; //初始化 public function _initialize() { header("Content-Type:text/html; charset=utf-8"); $admin_marked="qiblog-admin-mark"; $this->loginMarked = md5($admin_marked); } public function index() { return $this->fetch(); } public function login_do(Request $request) { if($this->request->isPost()){ $map['account'] = $request->post("username"); //用户名 $password = MD5($request->post("password"));//密码 $result = Db::name('admin')->field('id,account,login_count,status,password')->where($map)->find(); if($result){ if($password!=$result['password']) { $status['code']=0; $status['mess']="密码错误"; $status['url']=url("Login/index"); return $status; } if($result['status'] == 0){ $status['code']=0; $status['mess']="登录失败,账号被禁用"; $status['url']=url("Login/index"); return $status; } //所在的会员组 $table="auth_group g,db_auth_group_access a"; $group=Db::name($table)->where("g.id=group_id and uid=".$result['id'])->field("g.title")->find(); session('aid',$result['id']);//管理员ID session('account',$result['account']);//管理员密码 session('group',$group['title']);//会员组 //保存登录信息 $data['id'] = $result['id'];//用户ID $data['login_ip'] = $this->request->ip();//最后登录IP $data['login_time'] = time();//最后登录时间 $data['login_count'] = $result['login_count'] + 1; Db::name("admin")->update($data); //写入信息 $loginMarked = md5("qiblog-admin-mark"); $shell = md5($result['account']); $_SESSION[$loginMarked] = "$shell"; $shell.= "_" . time(); setcookie($loginMarked, "$shell", 0, "/"); $status['code']=1; $status['mess']="验证成功,正在跳转到首页"; $status['url']=url("Index/index"); return $status; }else{ $status['code']=0; $status['mess']="账户不存在"; $status['url']=url("Login/index"); return $status; } }else{ if (isset($_COOKIE[$this->loginMarked])) { $this->redirect("Index/index"); } unset($_COOKIE[$this->loginMarked]); $this->redirect("Login/index"); } } public function loginout() { session('aid',null);//注销 uid ,account session('username',null); setcookie("$this->loginMarked", NULL, -3600, "/"); unset($_SESSION["$this->loginMarked"], $_COOKIE["$this->loginMarked"]); session_destroy(); $this->redirect('Login/index'); } } ?>
auth类存放位置:根目录下\extend\auth auth是行创建的目录
打赏本站,你说多少就多少

本文地址:https://www.qi522.com/view/107.html
来 源:千奇博客
上一篇:开启全站https的方式