As aplicações PHP estão se tornando a cada dia mais complexas, aplicações de uso comercial, acadêmico e das mais diversas finalidades fazem necessário um controle mais apurado de acesso.
No CodeIgniter, obrigatoriamente estamos sempre acessando uma classe e um método de um controlador. Dessa forma, é possível mapear todas as possíveis ações e/ou caminhos disponíveis em uma aplicação e adicionar o controle de acesso aos métodos que desejamos controlar.
Desenvolvi uma biblioteca (librarie) para controlar o acesso dos usuários, o funcionamento é o seguinte.
Em uma tabela no banco de dados (sys_metodos), ficam guardados os nomes de classe e os métodos, mapeando todos os possíveis caminhos e em outra (sys_permissoes) ficam as ids dos usuários com os respectivos métodos a que eles têm acesso. Essa segunda tabela está relacionada à tabela de cadastro de usuários (tb_usuarios).

Figura 1 - Estrutura das tabelas necessárias ao sistema de autenticação
Seria bastante trabalhoso ter que popular a tabela de métodos manualmente, ou criar um Admin para ela, dessa forma, foi incluída uma rotina na própria biblioteca para que quando um método invocado por ela não for encontrado na tabela sys_metodos ele seja automaticamente criado. Dessa forma, na primeira vez em que um método for acessado, ninguém terá permissão de acesso, assim, será necessário parametrizar o sistema uma única vez no primeiro acesso. Depois poderá se construir uma área de administração para varrer a tabela de métodos e adicionar ou remover as permissões dos usuários.
O CodeIgniter provê uma maneira de checarmos "onde estamos", ou seja, em que classe e em que método.
Para verificar o nome da classe, utilize a seguinte linha de código:
$this->router->classE para recuperar o nome do método utilize:
$this->router->methodDessa forma, podemos passar para a biblioteca o caminho completo de onde estamos da seguinte forma:
$this->auth->check_logged($this->router->class , $this->router->method);Sendo auth o nome da biblioteca e check_logged o método que estamos acessando na biblioteca. Como essa biblioteca estará sendo acessada em muitas classes e métodos, é preferível carregar no autoload para que ela esteja sempre disponível em qualquer parte da aplicação.
Para proteger um método, basta incluir a linha de código conforme mostrado na primeira linha do método da seguinte forma.
class AreaRestrita extends Controller {
function __construct(){
parent::Controller();
}
function index(){
$this->auth->check_logged($this->router->class , $this->router->method);
}
}
?>Vejamos então como fica o código fonte da biblioteca. Salve o código-fonte a seguir com o nome de arquivo auth.php na pasta system/application/libraries.
class Auth
{
private $ci;
public function __construct(){
$this->ci = &get_instance();
}
function check_logged($classe,$metodo)
{
/*
* Criando uma instância do CodeIgniter para poder acessar
* banco de dados, sessionns, models, etc...
*/
$this->CI =& get_instance();
/**
* Buscando a classe e metodo da tabela sys_metodos
*/
$array = array('classe' => $classe, 'metodo' => $metodo);
$this->CI->db->where($array);
$query = $this->CI->db->get('sys_metodos');
$result = $query->result();
// Se este metodo ainda não existir na tabela sera cadastrado
if(count($result)==0){
$data = array(
'classe' => $classe ,
'metodo' => $metodo ,
'apelido' => $classe . '/' . $metodo,
'privado' => 1
);
$this->CI->db->insert('sys_metodos', $data);
redirect(base_url(). $classe . '/' . $metodo, 'refresh');
}
//Se ja existir tras as informacoes de publico ou privado
else{
if($result[0]->privado==0){
// Escapa da validacao e mostra o metodo.
return false;
}
else{
// Se for privado, verifica o login
$nome = $this->ci->session->userdata('nome');
$logged_in = $this->ci->session->userdata('logged_in');
$data = $this->ci->session->userdata('data');
$email = $this->ci->session->userdata('email');
$id_usuario = $this->ci->session->userdata('id_usuario');
$id_sys_metodos = $result[0]->id;
// Se o usuario estiver logado vai verificar se tem permissao na tabela.
if($nome && $logged_in && $id_usuario){
$array = array('id_metodo' => $id_sys_metodos, 'id_usuario' => $id_usuario);
$this->CI->db->where($array);
$query2 = $this->CI->db->get('sys_permissoes');
$result2 = $query2->result();
// Se não vier nenhum resultado da consulta, manda para página de
// usuario sem permissão.
if(count($result2)==0){
redirect(base_url().'home/sempermissao', 'refresh');
}
else{
return true;
}
}
// Se não estiver logado, sera redirecionado para o login.
else{
redirect(base_url().'home/login', 'refresh');
}
}
}
}
/**
* Método auxiliar para autenticar entradas em menu.
* Não faz parte do plugin como um todo.
*/
function check_menu($classe,$metodo){
$this->CI =& get_instance();
$sql = "SELECT SQL_CACHE
count(sys_permissoes.id) as found
FROM
sys_permissoes
INNER JOIN sys_metodos
ON sys_metodos.id = sys_permissoes.id_metodo
WHERE id_usuario = '" . $this->ci->session->userdata('id_usuario') . "'
AND classe = '" . $classe . "'
AND metodo = '" . $metodo . "'";
$query = $this->CI->db->query($sql);
$result = $query->result();
return $result[0]->found;
}
}Note que a biblioteca se encarrega de inserir os dados de métodos e classes que ainda não estejam cadastrados na tabela sys_metodos.
Quando um usuário tentar acessar uma área do website ou sistema em que ele não tenha privilégios, ele será redirecionado para uma página específica.
redirect(base_url().'home/sempermissao','refresh'); E que quando ele não estiver logado, será redirecionado para a página de login.
redirect(base_url().'home/login','refresh');Incluí











22 Comentários
Qual a sua opinião?