ThinkPHP3.2.3 RBAC权限漏洞完善

TP权限建立前两步看这里
1、http://www.fungj.com/information/rbac-thinkphp323-foundation-to-establish-database-permissions.html
2、http://www.fungj.com/information/rbac-thinkphp323-according-to-permissions-to-operate-the-display.html
在TP建立好权限后,有个漏洞,就是如果有原来的开发人员知道相关的控制器和写法,就能跳过前面的权限控制,直接操作。
例如,我的品字形框架,左边都是相关权限操作,而相关的操作方法都是由相关的控制器操作,所以一旦有人知道我的控制器相关位置修改url地址进行访问,那么权限操作就歇菜了。

解决思路:

每次用户访问的控制器和方法都需要和对应的角色里边的ac信息进行比较
ac信息里边存在这个控制器和方法就允许访问,否则禁止访问

首先,我前面做了个组建的目录Component,在这个目录下面在建一个AdminController.class.php文件,用于权限控制。
注意命名空间和使用的命名空间。

namespace Component;
use Think\Controller;

因为我组件这个目录是在根目录下,如果还有目录的话namespace前面也需要加上目录路径。
类依旧继承 Controller 就好。

全部代码为:

<?php

//普通控制器的父类
namespace Component;
use Think\Controller;

class AdminController extends Controller {
    //构造方法
    function __construct() {
        //先执行父类的构造方法,否则系统要报错
        //因为原先的构造方法默认是被执行的
        parent::__construct();

        //CONTROLLER_NAME ---Goods
        //ACTION_NAME  ----showlist
        //当前请求操作
        $now_ac = CONTROLLER_NAME . "-" . ACTION_NAME;

        //过滤控制器和方法,避免用户非法请求
        //通过角色获得用户可以访问的控制器和方法信息
        $sql = "select role_auth_ac from sw_manager a join sw_role b on a.mg_role_id=b.role_id where a.mg_id=" . $_SESSION['userid'];
        $auth_ac = M()->query($sql);
        $auth_ac = $auth_ac[0]['role_auth_ac'];

        //判断$now_ac是否在$auth_ac字符串里边有出现过
        //strpos函数如果返回false是没有出现,返回0 1 2 3表示有出现
        //管理员不限制
        //默认以下权限没有限制
        //Index/left  Index/right  Index/head  Index/index  Manager/login
        $allow_ac = array('Index-left', 'Index-right', 'Index-head', 'Index-index', 'Manager-login');
        if (!in_array($now_ac, $allow_ac) && $_SESSION['userid'] != 1 && strpos($auth_ac, $now_ac) === false) {
            $this->error('没有权限访问', U("Index/right"));
        }
    }
}
?>

然后在相应的控制器中,把原来默认继承的Controller改为继承AdminController就可以了。

但我想说的是,如果真有和自己一起开发的人跳出去搞你的话,也真心是交友不慎了。

但既然是学习嘛,也记录一下,另外我也有个自己的办法,当然这个只是验证是否为管理人员登录,不登录其他页面也是访问不了的方法。

//后台首页    
public function Index() {
    //获取SESSION里面的数据
    $username = session('username');
    $userid = session('userid');
    //检查SESSION里面的用户是否存在
    $dbuser = M('manager');
    $dbinfo = $dbuser->
    where("mg_name='$username'")->select();
    if ($dbinfo != null) {
        //判断是否登录
        $this->display();
    } else {
        $this->error('您还没有登录,请先登录!', U('Manager/login'));
        return flase;
    }
}

做好首页后,在其他管理页面的方法里把这个方法先实例化一下即可。

$this->Index();    //判断登录

这样子做个从SESSION里面得到的用户去MYSQL里去对比,如果没有的话,就算没登录,其他页面也一样登录不了。

最后修改:2016 年 09 月 29 日 02 : 35 PM
如果觉得我的文章对你有用,请随意赞赏

2 条评论

  1. 明余

    1064:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 [ SQL语句 ] : select role_auth_ac from sw_manager as a join sw_role as b on a.mg_role_id=b.role_id where a.mg_id=

    1. 风之翼灵
      @明余

      MYSQL是什么版本? 另外是TP的数据库表前缀有了么?

发表评论