用数组保护PHP函数?

时间:2016-05-09 21:48:13

标签: php

我目前正在创建一个具有多个不同访问级别的小型PHP站点。有些人可以访问所有部分(a,b,c,d),有些人只能访问特定部分(如b,d)。

目前,我有用户登录,并且根据mysql数据库中存储的凭据验证用户名/密码。此外,在登录时我创建一个列出用户有权访问的所有功能的数组。然后我将数组存储在它们的会话变量中。每个PHP页面在页面顶部都有以下代码,

   session_start();
if (!isset($_SESSION["is_auth"])) {
  header("location: login.php");
    exit;
   }

我的问题是, 如何限制对函数/页面的访问?我是否应该让每个函数再次调用数据库并检查用户是否可以访问该函数,或者仅仅验证特定函数是否在存储在用户会话中的数组中。

感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

可以假设会话内容是安全的,因为客户端无法访问它。

如果您的登录过程设置了$_SESSION选项,您可以查看此内容。

session_start();
if (!isset($_SESSION["is_auth"])) {
    header("location: login.php");
    exit;
}
// empty() matches to bool(false) and int(0), but throws no notice if index is undefined.
if (empty($_SESSION["allowed_area"]["area_a"])) {
    header("location: access_denied.php");
    exit;
}

答案 1 :(得分:0)

您不需要在每个页面上检查数据库中的用户凭据,因为会话变量是安全的。

但是你可能会在一段时间后检查它,因为让我们说你是否在你的管理面板中删除了一个用户或锁定了他的帐户或更改了他的密码,但是在那个用户已经登录之前。所以在那种情况下如果你没有在您的数据库中验证用户将不会被注销,并且他将在他关闭浏览器之前登录(他可能不会故意关闭它以保持登录到您的网站),您应该注意这种可能性。

第二个问题是会话劫持,如果有人获得了您的有效用户的会话cookie,那么他也将使用您的网站。因此,您应该在每个页面上使用session_regenerate_id(true);,以便每次将新会话ID分配给用户并删除之前的会话ID时。

答案 2 :(得分:0)

关于如何在服务器的任何资源上授予对任何用户的访问权限,我所做的是保存会话中的所有数据,之后在每个用户请求中,如果用户(或者更确切地说,是用户的角色)具有访问该资源的足够权限。

我建议使用框架作为codeigniter(它很容易学习它是如何工作的,并且有成千上万的教程),并且Ben Edmunds有一个库调用ion-auth。它有登录,注册(自动电子邮件发送以激活帐户 - 如果您配置 - ),恢复密码,几个安全功能,以访问用户。

对于权限,我使用的是这个库:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Permissions
{

    public function __construct()
    {
    }

    public function __call($method, $arguments)
    {
        if (!method_exists( $this->ion_auth_model, $method) )
        {
            throw new Exception('Undefined method Ion_auth::' . $method . '() called');
        }

        return call_user_func_array( array($this->ion_auth_model, $method), $arguments);
    }

    public function __get($var)
    {
        return get_instance()->$var;
    }

    public function control(){
        // controla la session

        if(!$this->session->userdata('id')) redirect(base_url("/login"), "refresh");    

        // valida los permisos
        $group = $this->permissions_model->lookUpGroup($this->session->userdata('user_id'));
        $menu = $this->permissions_model->lookUpPermission($this->uri->segment(1), $group->group_id);
        //echo "url: ".$this->uri->segment(1)." grup: ".$group->group_id."<br>";
        //var_dump($menu);
        //die();
        if((!$menu || empty($menu)) || $menu->read == 0 && $menu->menu_id != 12 ){
            redirect(base_url("/dashboard"), "refresh");
        }           

        // retorna permisos
        $menu = $this->permissions_model->getByLink($this->uri->segment(1));
        return $permisos = $this->permissions_model->permissions($menu->id, $this->session->userdata('user_id'));

    }

    public function getMenu(){  
        $ci = &get_instance();
        if($ci->session->userdata("id"))
        {
            $user_id = $ci->session->userdata("id");
            $father_query = "SELECT  u.id usuario, ug.user_id, ug.group_id, p.menu_id, p.read, p.insert, p.update, p.delete, p.group_id, m.*
            FROM users u
            JOIN users_groups ug        ON u.id = ug.user_id
            JOIN permisos p             ON ug.group_id = p.group_id
            JOIN menus m                ON p.menu_id = m.id
            WHERE u.id = ".$user_id."   AND m.active=1
            AND m.parent=0
            ORDER BY m.orden
            ";
            $query_padres = $ci->db->query($father_query);

            if($query_padres->num_rows()>0)
            {       
                foreach($query_padres->result() as $field)
                {
                    $consulta_hijos = "SELECT  u.id usuario, ug.user_id, ug.group_id, p.menu_id, p.read, p.insert, p.update, p.delete, p.group_id, m.*
                    FROM users u
                    JOIN users_groups ug        ON u.id = ug.user_id
                    JOIN permisos p             ON ug.group_id = p.group_id
                    JOIN menus m                ON p.menu_id = m.id
                    WHERE u.id = ".$user_id."   AND m.active=1
                    AND m.parent=".$field->id."
                    AND p.read=1
                    ORDER BY m.orden";
                    $sub_query = $ci->db->query($consulta_hijos);
                    if($sub_query->num_rows()>0){
                        $submenus = '';
                        $active_menu = '';
                        $active_menu_collapse = '';
                        foreach ($sub_query->result() as $result_dos) {
                                    if ($ci->uri->segment(1) == $result_dos->link && $ci->uri->segment(2) == $result_dos->sublink) {
                                        $submenus .= "<li class='active'><a href='". base_url($result_dos->link."/".$result_dos->sublink)."'><i class='".$result_dos->iconpath."'></i> ".$ci->lang->line($result_dos->descripcion)."</a></li>";
                                        $active_menu = 'active';
                                        $active_menu_collapse = 'collapse in';
                                    }else{
                                        $submenus .= "<li><a href='". base_url($result_dos->link."/".$result_dos->sublink)."'><i class='".$result_dos->iconpath."'></i> ".$ci->lang->line($result_dos->descripcion)."</a></li>";
                                    }
                        }

                        echo    "<li class='".$active_menu."'>
                                    <a href='javascript:;'><i class='".$field->iconpath."'></i><span class='title'>".$ci->lang->line($field->descripcion)."</span><span class='arrow'></span></a>
                                    <ul class='sub-menu'>
                                    ".$submenus."
                                    </ul>
                                </li>";
                    }
                    else if (($ci->uri->segment(1) == $field->link && $ci->uri->segment(2) == $field->sublink) || $ci->uri->segment(1) == '') {
                        echo "  <li class='active'>
                                    <a href='".base_url($field->link."/".$field->sublink)."'>
                                        <i class='".$field->iconpath."'></i> 
                                        <span class='title'>".$ci->lang->line($field->descripcion)."
                                        <span class='selected'></span>
                                    </a>
                                </li>";
                    }else{
                        echo "<li>
                                <a href='".base_url($field->link."/".$field->sublink)."'>
                                    <i class='".$field->iconpath."'></i> 
                                    <span class='title'>".$ci->lang->line($field->descripcion)."</span>
                                    <span class='selected'></span>
                                </a>
                            </li>";
                    }

                }
            }
        }
    }
}

在此之后,我在核心文件夹上创建了一个父控制器(从中扩展了每个要保证正确访问的控制器)。核心文件夹上的控制器示例:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Main_Father extends CI_Controller {

    public function __construct() {
        parent::__construct();
        //session_start();
        $this->load->helper('url');
        if($this->getPermissions())
        {
            //make some things before pass control to the authentic controller
        }
        else 
            redirect(base_url());
    }
    private function getPermissions()
    {
        $this->user = $this->ion_auth->user()->row();
        if($this->user)
        {
            //$this->data["permissions"]    = $this->permissions->control();
            if($this->permissions->control())
            {
                //make any function
                return true;
            }
            else return false;
        }
        else
        {
            if(strpos(base_url(uri_string()),"login")==false)
                redirect(base_url('/login'.$url));
            else return false
        }
    }
}

最后一个元素...... Permission_model

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Permissions_model extends CI_Model {

    function __construct() {
        parent::__construct();
    }


    function get_all(){
        $query = $this->db->get('groups');
        return $query->result();
    }

    function getAll(){
        $user_row = $this->ion_auth->user()->row();
        if (!$this->ion_auth->in_group(1, $user_row->id)){
            $query = $this->db
                ->select('p.*, g.name AS grupo, m.descripcion AS menu')
                ->join('groups g','p.group_id = g.id')
                ->join('menus m', 'p.menu_id = m.id')
                ->where('p.group_id !=', 1)
                ->get('permisos p');
        }else{
            $query = $this->db
                ->select('p.*, g.name AS grupo, m.descripcion AS menu')
                ->join('groups g','p.group_id = g.id')
                ->join('menus m', 'p.menu_id = m.id')
                ->get('permisos p');      
        }
        return $query->result();
    }

    //buscar
    function lookUp(/*$perpage,$start*/){
        $query = $this->db
            ->select('permisos.id AS id,
            menus.descripcion AS menu,
            groups.id AS id_grupo,
            groups.description  AS grupo,
            permisos.read AS Leer,
            permisos.insert AS Insertar,
            permisos.update AS Actualizar,
            permisos.delete AS Borrar,
            permisos.exportar AS Exportar,
            permisos.imprimir AS Imprimir')
            ->join('menus',     'menus.id = permisos.menu_id', 'inner')
            ->join('groups',    'groups.id = permisos.group_id', 'inner');

        if($where = $this->input->post('buscar', TRUE))
            $query = $this->db->where('permisos.id =', $where)
                ->or_where("menus.descripcion LIKE '%".$where."%'")
                ->or_where("groups.description LIKE '%".$where."%'");

        $query = $this->db
            ->get('permisos');
        return $query->result('array');
    }

    //count_buscar
    function count_lookUp($perpage,$start){
        $query = $this->db
            ->join('menus',     'menus.id = permisos.menu_id', 'inner')
            ->join('groups',    'groups.id = permisos.group_id', 'inner');
        if($where = $this->input->post('buscar', TRUE))
            $query = $this->db->where('id =', $where);
        $query = $this->db->limit($perpage,$start)
            ->get('permisos');
        return $query->num_rows();
    }

    function getByLink($link){
        $query = $this->db
            ->select('id')
            ->where('link',$link)
            ->get('menus');
        return $query->row();
    }
    //buscarPermiso
    function lookupPermission($url, $perfil){
        $query = $this->db
            ->select('p.read,p.menu_id')
            ->join('menus m', 'm.id = p.menu_id')
            ->where('p.group_id', $perfil)
            ->like('m.link', $url)
            ->get('permisos p');
        return $query->row();
    }
    //buscarGrupo
    function lookUpGroup($usuario){
        $query = $this->db
            ->select('group_id')
            ->where('user_id', $usuario)
            ->get('users_groups');
        return $query->row();
    }
    function permissions($menu, $id_usuario) {
        $query = $this->db
            ->select('u.id, up.group_id, p.*')
            ->join('users_groups up', 'up.user_id = u.id')
            ->join('permisos p', 'p.group_id = up.group_id')
            ->where('u.id =', $id_usuario)
            ->where('p.menu_id =', $menu)
            ->limit('1')
            ->get('users u');
        return $query->row();
    }
}

我希望它可以帮到你。

PS:1º)我不太喜欢getMenu函数,它不尊重MVC模式大炮,查询也不安全(它必须使用参数化方法?)。 2º)可以更改此功能创建的html。 3º)这里描述的大部分代码都不是我的... ion_auth库是由Ben Edmunds制作的,Permissions代码是由一个未知的“艺术家”制作的。 4º)如果你很谨慎,那么permissions_model上有很多东西可以升级......