Auth權限認證
本例采用auth權限認證,用戶和用戶組采用多對多關系處理,自動添加rule規則,帶有jquery-validator插件,自動控制菜單顯示或隱藏。
config.php中的配置
'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'//用戶信息表
)
第一步、Thinkphp3.2中的library下有Auth.class.php有所需的三個表及注釋。創建數據表。自己還需建一張用戶表。
n think_auth_rule,規則表(存放所有的權限規則)
n think_auth_group 用戶組表(存放一個用戶組有哪些權限)
n think_auth_group_access 用戶組明細表(其實就是叫用戶表和用戶組的中間表)
n think_user 用戶表(需自建)
第二步、config.php中配置auth認證。
'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'//用戶信息表
)
第三步、需要驗證的類都繼承CommonController。創建CommonController.class.php文件。(此類針對多入口的情況)
<?php
namespace Admin\Controller;
use Think\Controller;
class CommonController extends Controller {
public function _initialize () {
if(!isset($_SESSION[C('USER_AUTH_KEY')])){ //判斷是否有uid
$this->redirect("Public/login");
}
$Auth = new \Think\Auth();
$module_name=CONTROLLER_NAME.'/'.ACTION_NAME;
if($_SESSION['uname']==C('ADMIN_AUTH_KEY')){ //以用戶名來判斷是否是超級管理員,繞過驗證,不用用戶組來判斷的原因是用戶組有時候是中文 ,而且常刪除或更改。
return true;
}
if(!$Auth->check($module_name,$_SESSION[C('USER_AUTH_KEY')])){
$this->error('沒有權限');
}
}
}
第四步、登錄驗證的PublicController和以前都差不多。創建PublicController.class.php
<?php
namespace Admin\Controller;
use Think\Controller;
class PublicController extends Controller {
public function index(){
$this->display();
}
//登錄頁
public function login(){
$this->display();
}
//登出
public function logout(){
if($_SESSION[C('USER_AUTH_KEY')]) {
session_destroy();
$this->redirect("Public/login");
}else {
$this->error('已經登出!');
}
}
//驗證登陸表單
public function checkLogin(){
$username=I('username','');
$password=I('password','');
$verify_code=I('verify','');
if($username==''||$password==''||$verify_code==''){
$this->redirect("Public/login");
}
if(!$this->_verifyCheck($verify_code)){
$this->error("驗證碼錯誤!!!");
}
$user=M('user')->where(array('username'=>$username))->find();
if(!$user||md5($password)!=$user['password']){
$this->error("用戶名或密碼錯誤!!!");
}
if(!$user['status']){ //status為0時表示鎖定
$this->error("用戶被鎖定!!!");
}else{
$data['login_ip'] = get_client_ip();
$data['last_login_time']=time();
if(M("user")->where(array('id'=>$user['id']))->save($data)){
M("user")->where(array('id'=>$user['id']))->setInc("login_num");
}
session(C('USER_AUTH_KEY'),$user['id']);
session('uname',$user['username']);
$this->success("登錄成功...",U("Index/index"));
}
}
//驗證碼
public function verify(){
$config = array(
'fontSize' => 20, // 驗證碼字體大小
'length' => 1, // 驗證碼位數
'useNoise' => false, // 關閉驗證碼雜點
'imageH' => 50, // 驗證碼圖片高度
'imageW' => 200, // 驗證碼圖片寬度
);
$Verify =new \Think\Verify($config);
$Verify->entry();
}
//驗證驗證碼
private function _verifyCheck($code, $id = ''){
$verify = new \Think\Verify();
return $verify->check($code, $id);
}
}
到這里,auth的權限認證就基本完成
第五步、創建AuthController.class.php(邏輯代碼如下,就是一些CURD),多加了一個register方法,用來自動把規則的放入數據庫中.本人把register放在function.php中方便其他類調用。用戶和用戶組采用多對多的關系處理,方便權限更為精細。
<?php
namespace Admin\Controller;
use Think\Controller;
class AuthController extends CommonController {
//Auth認證管理
public function index(){
//獲取用戶信息
$user=D("user")->relation(true)->field("password",true)->select();
$this->user=$user;
//獲取用戶組信息
$group=M("auth_group")->select();
$obj=M("auth_rule");
foreach($group as $k=>$v){
$map['id'] = array('in',$group[$k]['rules']);
$group[$k]['group']=$obj->where($map)->select();
}
$this->group=$group;
//獲取rule規則
$this->rule=M("auth_rule")->select();
//$ip = new \Org\Net\IpLocation("UTFWry.dat");
//$location=$ip->getlocation();
//p($location);die;
//p($group);die;
$this->display();
}
//添加后台用戶及表單處理
public function user(){
if(IS_POST){
$data=array(
'username'=>I('username','','trim'),
'remark'=>I('remark','','trim'),
'password'=>I('password','','md5'),
'status'=>I('status',0,'intval'),
'rsgtime'=>$_SERVER['REQUEST_TIME'],
'login_num'=>0
);
if(!isset($_POST['role_id'])){
$this->error("請選擇用戶組...");
}
if($data['password']!=md5($_POST['repassword'])){
$this->error("兩次密碼不一致...");
}
if(M("user")->where(array('username'=>$data['username']))->find()){
$this->error("用戶名已存在...");
}
if($lastInsertId=M("user")->add($data)){
foreach($_POST['role_id'] as $k=>$v){
$arr=array(
'uid'=>$lastInsertId,
'group_id'=>$_POST['role_id'][$k]
);
M("auth_group_access")->add($arr);
}
M("auth_group_access")->add($arr);
$this->success("添加成功...",U("Auth/index"));
}else{
$this->error("添加失敗...");
}
}else{
$this->group=M("auth_group")->field("id,title")->select();
$this->display();
}
}
//添加后台用戶組及表單處理
public function group(){
if(IS_POST){
$data=array(
'title'=>I('title','','trim'),
'status'=>I('status',0,'intval')
);
if(M("auth_group")->where(array('title'=>$data['title']))->find()){
$this->error("用戶組名稱已存在...");
}
if(M("auth_group")->add($data)){
$this->success("添加成功...",U("Auth/index"));
}else{
$this->error("添加失敗...");
}
}else{
$this->display();
}
}
//添加后台權限及表單處理
public function auth(){
if(IS_POST){
$data=array(
'name'=>I('name','','trim'),
'title'=>I('title','','trim'),
'condition'=>I('condition','','trim'),
'status'=>I('status',0,'intval'),
'type'=>I('type',0,'intval'),
);
if(M("auth_rule")->add($data)){
$this->success("添加成功...",U("Auth/index"));
}else{
$this->error("添加失敗...");
}
}else{
$this->display();
}
}
//注冊rule規則
public function register(){
$class_name=get_class();
return register($class_name);
}
//刪除用戶組
public function deleteGroup(){
if(IS_GET){
if(!isset($_GET['id'])){
return false;
}
$id=I("id",0,"intval");
if(!$id){
return false;
}
if(M("auth_group")->where(array("id"=>$id))->delete()){
M("auth_group_access")->where(array("group_id"=>$id))->delete();
$this->success("刪除成功...",U("Auth/index"));
}else{
$this->error("刪除失敗...");
}
}
}
//修改用戶組
public function modifyGroup(){
if(IS_GET){
if(!isset($_GET['id'])){
return false;
}
$id=I("id",0,"intval");
if(!$id){
return false;
}
$group=M("auth_group")->where(array("id"=>$id))->find();
$rule=M("auth_rule")->select();
foreach($rule as $k=>$v){
if(in_array($rule[$k]['id'],explode(',',$group['rules']))){
$rule[$k]['is_checked']=1;
}else{
$rule[$k]['is_checked']=0;
}
}
$this->rule=$rule;
$this->group=$group;
$this->id=$id;
//p($rule);die;
$this->display();
}elseif(IS_POST){
$data=array(
'title'=>I("title","","trim"),
'rules'=>implode(",",$_POST['rule']),
'status'=>I("status","","trim")
);
if(M("auth_group")->where(array("id"=>$_POST['id']))->save($data)){
$this->success("修改成功...",U("Auth/index"));
}else{
$this->error("修改失敗...");
}
}
}
//刪除RULE
public function deleteRule(){
if(IS_GET){
if(!isset($_GET['id'])){
return false;
}
$id=I("id",0,"intval");
if(!$id){
return false;
}
if(M("auth_rule")->where(array("id"=>$id))->delete()){
$this->success("刪除成功...",U("Auth/index"));
}else{
$this->error("刪除失敗...");
}
}
}
//修改RULE
public function modifyRule(){
if(IS_POST){
if(!isset($_POST['id'])){
return false;
}
$id=I("id",0,"intval");
unset($_POST['id']);
if(!$id){
return false;
}
if(M("auth_rule")->where(array("id"=>$id))->save($_POST)){
$this->success("修改成功...",U("Auth/index"));
}else{
$this->error("修改失敗...");
}
}
}
//刪除用戶
public function deleteUser(){
if(IS_GET){
if(!isset($_GET['id'])){
return false;
}
$id=I("id",0,"intval");
if(!$id){
return false;
}
if(M("user")->where(array("id"=>$id))->delete()){
M("auth_group_access")->where(array("uid"=>$id))->delete();
$this->success("刪除成功...",U("Auth/index"));
}else{
$this->error("刪除失敗...");
}
}
}
//修改用戶
public function modifyUser(){
if(IS_POST){
$id=I("id",0,"intval");
if(!$id){
return false;
}
$data['username']=I("username","","trim");
$data['remark']=I("remark","","trim");
$data['status']=I("status",0,"intval");
$tmp=0;
if(isset($_POST['role_id'])){
M("auth_group_access")->where(array("uid"=>$id))->delete();
foreach ($_POST['role_id'] as $key => $value) {
if(M("auth_group_access")->add(array("uid"=>$id,"group_id"=>$_POST['role_id'][$key]))){
$tmp=1;
}
}
}
if(trim($_POST['password'])){
if(md5($_POST['password'])!=md5($_POST['repassword'])){
$this->error("兩次密碼輸入不一致...");
}else{
$data['password']=I("password","","md5");
}
}
if(M("user")->where(array("id"=>$id))->save($data)){
$this->success("修改成功...",U("Auth/index"));
}else{
if($tmp){
$this->success("修改成功...",U("Auth/index"));
}else{
$this->error("修改失敗...");
}
}
}elseif(IS_GET){
if(!isset($_GET['id'])){
return false;
}
$id=I("id",0,"intval");
if(!$id){
return false;
}
$this->user=M("user")->where(array('id'=>$id))->field("password",true)->find();
$user_group=M("auth_group_access")->where(array("uid"=>$id))->select();
$group=M("auth_group")->select();
foreach($user_group as $key => $value){
$user_group[$key]['group_name']=M("auth_group")->where(array("id"=>$user_group[$key]['group_id']))->getField("title");
}
$this->user_group=$user_group;
$this->group=$group;
$this->display();
}
}
}
function.php如下:(authCheck方法會在模板中有使用,用來控制菜單等顯示或隱藏,不需自己寫sql來循環判斷顯不顯示)
/**
* 注冊rule規則
* @param class_name string 類的名稱
* @return str 返回錯誤或者正確信息
*/
function register($class_name){
$data=get_class_methods($class_name);
//把一些父類的方法過濾掉 $arr=array('_initialize','__set','__construct','display','show','fetch','buildHtml','theme','assign',' __set','get','__get','__isset','__call','error','success','ajaxReturn','redirect','__destruct');
foreach($arr as $k=>$v){
if(in_array($arr[$k],$data)){
$tmp=array_keys($data,$arr[$k]);
unset($data[$tmp[0]]);
}
}
$obj=M("auth_rule");
$msg='';
foreach($data as $k=>$v){
$data[$k]=CONTROLLER_NAME.'/'.$data[$k];
if(!$obj->where(array('name'=>$data[$k]))->find()){
if($obj->add(array('name'=>$data[$k]))){
$msg=$msg.$data[$k].'注冊成功\n';
}else{
$msg=$msg.$data[$k].'注冊失敗\n';
}
}else{
$msg=$msg.$data[$k].'已注冊\n' ;
}
}
echo "<script>alert('".$msg."');history.back(-1);</script>";
}
/**
* 控制模板中菜單的顯示
* @param rule string|array 需要驗證的規則列表,支持逗號分隔的權限規則或索引數組
* @param uid int 認證用戶的id
* @param string mode 執行check的模式
* @param relation string 如果為 'or' 表示滿足任一條規則即通過驗證;如果為 'and'則表示需滿足所有規則才能通過驗證
* @return boolean 通過驗證返回true;失敗返回false
*/
function authCheck($rule,$uid,$type=1, $mode='url', $relation='or'){
$auth=new \Think\Auth();
//獲取當前uid所在的角色組id
//$groups=$auth->getGroups($uid);
if($_SESSION['uname']==C('ADMIN_AUTH_KEY')){
return true;
}
return $auth->check($rule,$uid,$type,$mode,$relation)?true:false;
}
注:模板中使用authCheck的方法,在你需要進行顯示或者隱藏的地方加上條件就可以了。
<ul class="nav nav-tabs nav-stacked main-menu">
<if condition="authCheck('Auth/index',$_SESSION[C('USER_AUTH_KEY')])">
<li class="nav-header hidden-tablet"><i class="icon-user"></i> Auth權限認證 </li>
<li>
<a class="ajax-link" href="{:U('Auth/index')}"><span class="hidden-tablet"> <i class="icon-th"></i> Auth認證 </span></a>
</li>
</if>
</ul>
最后一步、創建UserModel.class.php
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 14-10-20
* Time: 下午12:54
*/
namespace Admin\Model;
use Think\Model\RelationModel;
class UserModel extends RelationModel{
//關聯查詢用戶所屬的用戶組
protected $_link = array(
'auth_group' => array(
'mapping_type' => self::MANY_TO_MANY,
'class_name' => 'auth_group',
'mapping_name' => 'classify',
'foreign_key' => 'uid',
'relation_foreign_key' => 'group_id',
'relation_table' => 'think_auth_group_access'
)
);
}