segunda-feira, 16 de novembro de 2015

Autenticação com PHP e Postgres

Hoje veremos como efetuar uma operação de login utilizando o Postgres.
Para este tutorial é necessário que tenha o Postgres e o pgAdmin instalado, e saiba conceitos básicos de Orientação a Objetos.

Para começar, vamos dividir a estrutura do nosso aplicativo em 3 camadas, de acordo com o padrão MVC (Model – View – Controller).

Um Pouco sobre MVC

MVC é um Design Pattern (Padrão de Projeto) estrutural. Ele divide o aplicativo em 3 camadas onde:

M = Model (Responsável pela conexão com o Banco de Dados)
V = View (Apresentação para o usuário)
C = Controller (Responsável pela lógica)

Algumas regras:
Todo e qualquer acesso ao Banco de dados deve ser feito através da camada Model.
A View é responsável pela apresentação ao usuário.
O controller deve fazer a comunicação entre a View e o Model. Ele solicita os dados para a camada Model, processa, e envia para a View.

Tendo esses conceitos definidos, vamos montar a nossa estrutura.
Esse tutorial foi criado em ambiente linux, portanto crie um novo diretório com o nome appAuth na pasta definida pelo seu Apache para os sites, no linux é /var/www


Dentro dela Criaremos a seguinte estrutura:


Uma coisa bastante chata no PHP são os caminhos relativos que você precisa definir quando está incluindo arquivos ao seu script. Por exemplo, se você estiver no diretório controller/ e precisar incluir um arquivo que está em model/ você pode inseri-lo desta forma:

require_once '../model/arquivo.php';

Esta linha importa um arquivo para o seu script usando o caminho relativo. O ../ volta um nível no diretório e entra em model/ trazendo o aquivo.php.

Desta forma os caminhos dos require`s ou include`s ficariam confusos muito facilmente. Imagine o seguinte caminho:

require_once '../../../model/arquivo.php';

ou

require_once '../../../../../../../../model/arquivo.php';

Por esse motivo eu costumo usar o método do PHP set_include_path() no inicio do meu script.
Ele inclui paths da sua aplicação temporariamente ao php.ini apenas para a execução do script.

Na pasta root da nossa aplicação crie o arquivo init.php e insira o conteúdo abaixo:

<?php
/**
 * Incluindo os paths dos diretorios usados na aplicação
 */

$model_path = dirname(__FILE__).DIRECTORY_SEPARATOR.'model';
$controller_path = dirname(__FILE__).DIRECTORY_SEPARATOR.'controller';
$view_path = dirname(__FILE__).DIRECTORY_SEPARATOR.'view';

set_include_path(get_include_path() .
        PATH_SEPARATOR . $model_path .
        PATH_SEPARATOR . $controller_path .
        PATH_SEPARATOR . $view_path
        );

Em cada uma das variáveis, estamos inserindo o caminho absoluto do path para cada camada da aplicação:

model= /var/www/appAuth/model/
controller = /var/www/appAuth/controller/
view = /var/www/appAuth/view/

Desta forma, em qualquer parte do nosso aplicativo podemos chamar qualquer arquivo do model, view ou controller de forma mais legivel e livre de erros:

require_once 'model/arquivo.php';

Após este passo, vamos inserir o init.php no arquivo index.php, que é o arquivo que será executado por padrão ao nosso site ser requisitado.

<?php
require_once 'init.php';


A Camada Model:

Primeiramente, vamos criar a nossa tabela de usuários para que possamos fazer a inserção e verificação.

CREATE TABLE usuario
(
  id_usuario serial NOT NULL,
  nome character varying(70) NOT NULL,
  usuario character varying(15),
  senha character varying(8),
  CONSTRAINT usuario_pkey PRIMARY KEY (id_usuario)
)

Na pasta model/, vamos criar o arquivo Conexao.php.
Para fins didáticos, vamos abrir mão de algumas boas práticas de desenvolvimento e segurança. Isso ficará para outro post.

<?php

Class Conexao
{
    private static $instance = null;
       
    private $host = 'localhost';
    private $dbName = 'appAutentica';
    private $user = 'postgres';
    private $password = 'postgres';
   
    private $sock = null;
   
    private function __construct() { }
       
    public static function getInstance() {
        if (Conexao::$instance == null) {
                Conexao::$instance = new Conexao();
        }
        return Conexao::$instance;
    }

    public function conectarDB() {       
        $this->sock = pg_connect("host=$this->host user=$this->user password=$this->password dbname=$this->dbName") or die("Não foi possível conectar");               
    }
   
    public function close() {
        pg_close($this->sock);
        $this->sock = null;
    }
       


    function autentica($usuario, $senha) {
        $this->conectarDB();
       
        $sql = "SELECT * FROM usuario WHERE usuario = '$usuario' AND senha = '$senha'";
        $result = pg_query($this->sock, $sql);
        $user = pg_fetch_assoc($result);
       
        $this->close();
       
        if($user)
            return true;
        else
            return false;
    }
   
}
           
Temos aqui a classe Conexão. Ela é um Singleton. Daremos uma atenção especial ao método autentica(), que recebe duas strings, monta a sql e envia para o banco.
Basicamente, o que ele faz é perguntar para o banco se existe algum usuário com o login e senha recebidos por parâmetro. Em caso positivo, ele retorna o booleano true, caso contrário retorna false.

Como já temos agora o nosso ponto de conexão com o banco de dados, vamos trabalhar na camada Controller.

A Camada Controller:

Como dito anteriormente, a camada Controller além de possuir a lógica do aplicativo, ela atua como um intermediário entre o Model e a View.
Crie um arquivo chamado Autenticacao.php em /controller.

Com esta classe, vamos trabalhar com métodos estáticos, porque para o nosso propósito não é necessário o uso de objetos.

<?php
require_once 'model/Conexao.php';

class Autenticacao {
   
    public static function autentica($usuario, $senha) {
        $retornoOk = Conexao::getInstance()->autentica($usuario, $senha);
       
        return $retornoOk;
    }
}

O código acima importa a classe Conexao.php.  Como ela é um Singleton, pegamos a sua instância única através do método getInstance e executamos o método autentica do Model. Adicionamos o resultado da operacao na variável booleana $retornoOk e a retornamos para quem a solicitou.


A Camada View:

No nosso exemplo, farei com que a view faça as chamadas para o controller. Aqui ela terá um pouco de voz ativa para exigir que tipo de tratamento ela precisa, mas isso pode ser feito de várias outras formas.

Vamos trabalhar no arquivo index.php.

<?php
session_start();

require_once 'init.php';
require_once 'controller/Autenticacao.php';


$usuario = isset($_POST['tx_login']) ? $_POST['tx_login'] : '';
$senha = isset($_POST['tx_senha']) ? $_POST['tx_senha'] : '';

if (!empty($usuario) && !empty($senha)) {
   
    $autenticado = Autenticacao::autentica($usuario, $senha);
   
    if ($autenticado) {
        $_SESSION['autenticado'] = true;
        die("Autenticacao efetuada com sucesso");
       
    } else {
        die("A autenticacao falhou.");
    }
}
?>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title></title>
    </head>
    <body>
        <form id="frmLogin" name="frmLogin" action="index.php" method="post">
            Login <input name="tx_login" maxlength="15"/>
            Senha <input name="tx_senha" maxlength="15"/>
            <input type="submit" name="btn_submit" value="Ok"/>
        </form>
    </body>
</html>

Este aquivo index.php está dividido em duas partes. A primeira é aonde ele faz a requisição para o Controller verificar se o usuário e senha digitado pelo usuário estão corretos. Se sim é exibida a mensagem  Autenticacao efetuada com sucesso, se não, A autenticacao falhou.
A segunda parte é um formulário HTML com os campos Login e senha. O action deste form é o próprio index.php, e as variáveis do formulário são recuperadas através da variável $_POST.

Abraços e até a próxima.

Nenhum comentário:

Postar um comentário