Canais iMasters

PHP + Desenvolvimento + CMS + CodeIgniter

Criando uma biblioteca para controle de acesso por usuário aplicada a classes e métodos com o CodeIgniter

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->class

E para recuperar o nome do método utilize:

$this->router->method

Dessa 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í


Comente também

22 Comentários

Jean Nascimento
Jean Nascimento

Muito interessante seu artigo, parabéns!!!

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Obrigado. Espero que seja útil para a galera. Abraços.

Prof. Flavio Marcello Strelow
Prof. Flavio Marcello Strelow

Parabéns pelo artigo.

Fabio Caliari
Fabio Caliari

Show de Bola Ademir. Continue assim. Um abração.

Thallis Ferreia Soares
Thallis Ferreia Soares

Muito bom, parabéns

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Obrigado. Espero te ajudado de alguma forma.

GilsonDias
GilsonDias

Explanação estruturada, consistente com exemplos práticos e assimiláveis. Não lí o livro, imagina quando o fizer. PHP está mudando de cena com tais abordagens. Excelente!!!

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Olá a todos, acabei esquecendo uma linha de código no controlador home.php que é um helper para escrita de logs que criei. Por favor, comentem ou excluam a linha.

$this->load->helper('logs');

Caso alguém tenha interesse no código do helper para escrita de Log basta pedir em PVT.
Abraços e obrigado ao Luiz Sobral que alertou.

Tylër
Tylër

Oi, gostaria de saber se este framework possui mais funcionalidades e liberdade de programação que o cakePHP, pois estou a procura de algo que facilite e dê liberdade de desenvolvimento..

Obrigado!

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Olá Tylër, o CodeIgniter é semelhante ao Cake, já trabalhei com o Cake porém em um número menor de projetos do que com os quais trabalhei com o CodeIgniter.

O meu ponto de vista é que o CodeIgniter permite muita flexibilidade. Muita mesmo. Você pode estender as funcionalidades do Core através de Hooks. Você pode criar libraryes (meu favorito) e helpers.

E de modo geral ele não obstrui as funcionalidades nativas do PHP (observar algum cuidado com sessions e cookies) deste modo, permitindo mesclar funções nativas com as do Framework (Não muito ortodoxo).

A comunidade do CodeIgniter vem crescendo muito no Brasil, em breve deveremos ter um novo website para o www.codeigniter.com.br com mais interatividade. E a documentação é boa e clara.

Espero ter ajudado a esclarecer.
Abraços
Ademir

Marco
Marco

Disponibiliza esse helper do log = ]

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Olá Marco, o arquivo poderá ser baixado aqui: www.ademirgabardo.com.br/logs_helper.rar

Eduardo Matos
Eduardo Matos

Bom tutorial. É uma pena que o Codeigniter não tenha um componente próprio pra algo tão importante.
Na classe Auth você usa duas propriedades pra acessar a mesma instância ($this->ci e $this->CI), como está assinalado por referência não causa nenhum problema, mas acho que poderia ficar só com 1, pra manter a consistência.

Abraços

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Olá Eduardo, a versão 2.0 que está para ser lançada em breve deverá trazer modificações neste sentido. Não mencionaram nada sobre um componente próprio de autenticação, mas existem muitas bibliotecas como esta que eu criei na net. Algumas muito mais elaboradas inclusive com verificação de login com Captcha e tudo mais. Obrigado pelo comentário.

Abraços.

aureo souto
aureo souto

Muito bom! Consegui entender bem a idéia deste controle de acesso.Valeu

acs
acs

omecei agora, existe algum tutorial para 2.0 ?

Carlos Vargas
Carlos Vargas

Show de bola. Parabéns. Será muito útil seu artigo. Também gostaria de saber os impactos da versão 2.0 do CI para essa lib.

Abraço!

Hugo  Júnior
Hugo Júnior

Estou estudando o CI, e uma das funções que senti falta foi em relaçao a autenticação, mais achei bem bacana essa e vou testar e adaptar ao meu projeto.

Só um dúvida que me veio em mente, essa é a melhor forma de fazer o controle de acessos utilizando o codeIgniter?

Desde já agradeço pelo empenho e tutorial.

Eduardo Lima
Eduardo Lima

Ademir gostaria muito de estar lendo o livro que escreveu, mas não encontro em lugar algum, pode me ajudar ? abs. e parabens pelo artigo.

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Olá Galera, desculpa a demora em responder, época de TCC tenho andado meio OFF. Eu uso essa library com o CI2.0, não precisei mudar muita coisa. Se é a melhor? Não acredito que seja, mas para mim vem resolvendo muito bem minhas necessidades. Existem outras que inclusive permitem autenticação com conta do Facebook entre outras alternativas.
No meu caso, preciso de um controle específico sobre qual usuário pode fazer o que.
E ainda, eu tenho algumas coisas de Log que implementei para os sistemas que mantenho.

Sobre o Livro, está esgotado já. Talvez a editora tenha algum exemplar que retornou de consignação. www.novatec.com.br

Qual a sua opinião?

Comentários considerados ofensivos serão moderados.

Parceiros

IBM
PagSeguro
Internet Innovation
Dialhost
HostNet
Tecla
KingHost
DotStore
Dinamize