LAB-8

Tela de Login

1. Login Simples com Array

Estrutura dos arquivos do projeto:

/
├── login.php # Tela de login (formulário que envia para processa_login.php)
├── processa_login.php # Processa o formulário, autentica e inicia a sessão
├── pagina_restrita.php # Página protegida, só acessível ao usuário autenticado
├── logout.php # Encerra a sessão e faz logout

Descrições:

  • login.php: Mostra um formulário de login, trata mensagens de erro e envia os dados para autenticação.
  • processa_login.php: Valida os dados, autentica o usuário a partir de um array, inicia uma sessão e redireciona.
  • pagina_restrita.php: Exemplo de página apenas para usuários logados. Redireciona para login.php se não estiver autenticado.
  • logout.php: Destrói a sessão do usuário e redireciona para o login.

Código PHP completo e comentado

1. login.php

				
					<?php
session_start();
// Se já estiver autenticado, redireciona para a página restrita
if (isset($_SESSION['autenticado']) && $_SESSION['autenticado'] === true) {
    header("Location: pagina_restrita.php");
    exit();
}
?>

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <title>Login Simples</title>
</head>
<body>
    <h2>Login</h2>
    <!-- Exibe mensagem de erro, se existir -->
    <?php if (isset($_SESSION['erro_login'])): ?>
        <p style="color:red;"><?php echo $_SESSION['erro_login']; unset($_SESSION['erro_login']); ?></p>
    <?php endif; ?>
    <form action="processa_login.php" method="post">
        <label>Email:</label><br>
        <input type="email" name="email" required><br><br>
        <label>Senha:</label><br>
        <input type="password" name="senha" required><br><br>
        <input type="submit" value="Entrar">
    </form>
</body>
</html>
				
			

2. processa_login.php

				
					<?php
session_start();

// Array de usuários válidos (substitua por seus próprios usuários)
$usuarios = [
    ['email' => 'usuario1@example.com', 'senha' => 'senha123'],
    ['email' => 'usuario2@example.com', 'senha' => 'senha456'],
    // Adicione mais usuários conforme necessário
];

// Validação básica dos dados
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$senha = filter_input(INPUT_POST, 'senha', FILTER_SANITIZE_STRING);

if (!$email || !$senha) {
    $_SESSION['erro_login'] = 'Preencha todos os campos corretamente.';
    header('Location: login.php');
    exit;
}

// Procura usuário válido no array
$usuario_autenticado = false;
foreach ($usuarios as $usuario) {
    if ($usuario['email'] === $email && $usuario['senha'] === $senha) {
        $usuario_autenticado = true;
        break;
    }
}

if ($usuario_autenticado) {
    // Usuário autenticado com sucesso, registra sessão e redireciona
    session_regenerate_id(true); // importante para evitar sequestro de sessão
    $_SESSION['autenticado'] = true;
    $_SESSION['email_usuario'] = $email;
    header('Location: pagina_restrita.php');
    exit;
} else {
    $_SESSION['erro_login'] = 'Email ou senha inválidos.';
    header('Location: login.php');
    exit;
}
				
			

3. pagina_restrita.php

				
					<?php
session_start();
// Protege a página: permite acesso apenas se autenticado
if (!isset($_SESSION['autenticado']) || $_SESSION['autenticado'] !== true) {
    header('Location: login.php');
    exit;
}
?>

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <title>Página Restrita</title>
</head>
<body>
    <h2>Bem-vindo(a), <?php echo htmlspecialchars($_SESSION['email_usuario']); ?>!</h2>
    <p>Você está em uma página protegida.</p>
    <a href="logout.php">Sair</a>
</body>
</html>
				
			

4. logout.php

				
					<?php
session_start();

// Limpa todos os dados da sessão e destrói a sessão
$_SESSION = [];
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}
session_destroy();

header("Location: login.php");
exit;
				
			

O que são sessões em PHP?

Sessão é um mecanismo que permite manter dados do usuário enquanto ele navega pelo site. No PHP, ao usar session_start(), um identificador exclusivo (ID da sessão) é criado e mantido (geralmente via cookies). Com isso, dados gravados em $_SESSION ficam disponíveis em todas as páginas enquanto a sessão estiver ativa.

Como proteger páginas restritas?

  • Verificação: Sempre no topo das páginas restritas (ex: pagina_restrita.php), deve haver verificação se o usuário está autenticado (por exemplo, checando $_SESSION[‘autenticado’]).
  • Redirecionamento: Se não estiver autenticado, redirecione com header(‘Location: login.php’) e interrompa o script com exit;.
  • Destruição de sessão no logout: Ao sair, limpe o array $_SESSION, apague o cookie de sessão e use session_destroy(). Isso impede que a sessão anterior seja reutilizada.

2.Login Simples e Cadastro de Usuário com Banco de Dados

Estrutura sugerida:

/
├── conexao.php # Conexão PDO com o banco MySQL
├── login.php # Formulário de login
├── processa_login.php # Processo de validação/autenticação de login
├── pagina_restrita.php # Exemplo de página protegida
├── logout.php # Logout e destruição de sessão
├── cadastrar.php # Cadastro de novo usuário

Resumo:

  • conexao.php: Centraliza a conexão PDO ao banco de dados.
  • login.php: Tela para o usuário entrar no sistema. Link para cadastro se não for cadastrado.
  • processa_login.php: Valida entrada, checa credenciais e inicia sessão.
  • pagina_restrita.php: Exemplo de uso de sessão para proteger uma página.
  • logout.php: Limpa e encerra sessão.
  • cadastrar.php: Tela/procedimento para criar novo usuário.

Código PHP completo e comentado

1. conexao.php

				
					<?php
// Conexão utilizando PDO
$host = 'localhost';
$dbname = 'meu_banco';
$user = 'root';
$pass = 'SUA_SENHA'; // Altere conforme seu ambiente

try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Erro na conexão com o banco de dados: " . $e->getMessage());
}
?>
				
			

2. login.php

				
					<?php
session_start();
// Se já está autenticado, vai direto para área restrita
if (isset($_SESSION['autenticado']) && $_SESSION['autenticado'] === true) {
    header("Location: pagina_restrita.php");
    exit();
}
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <h2>Login</h2>
    <?php if (isset($_SESSION['erro_login'])): ?>
        <p style="color:red;"><?php echo $_SESSION['erro_login']; unset($_SESSION['erro_login']); ?></p>
    <?php endif; ?>
    <?php if (isset($_SESSION['msg_sucesso'])): ?>
        <p style="color:green;"><?php echo $_SESSION['msg_sucesso']; unset($_SESSION['msg_sucesso']); ?></p>
    <?php endif; ?>
    <form action="processa_login.php" method="post">
        <label>Email:</label><br>
        <input type="email" name="email" required><br><br>
        <label>Senha:</label><br>
        <input type="password" name="senha" required><br><br>
        <input type="submit" value="Entrar">
    </form>
    <p>Você ainda não é cadastrado? <a href="cadastrar.php">Cadastre-se aqui</a></p>
</body>
</html>
				
			

3. processa_login.php

				
					<?php
session_start();
require_once 'conexao.php';

// Coletando e validando entradas
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$senha = filter_input(INPUT_POST, 'senha', FILTER_UNSAFE_RAW);

if (!$email || !$senha) {
    $_SESSION['erro_login'] = "Preencha todos os campos corretamente.";
    header("Location: login.php");
    exit;
}

try {
    $stmt = $pdo->prepare("SELECT id, email, senha FROM usuarios WHERE email = :email LIMIT 1");
    $stmt->execute(['email' => $email]);
    $usuario = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($usuario && password_verify($senha, $usuario['senha'])) {
        // Autenticado com sucesso
        session_regenerate_id(true); // Previne fixation
        $_SESSION['autenticado'] = true;
        $_SESSION['email_usuario'] = $usuario['email'];
        $_SESSION['id_usuario'] = $usuario['id'];
        header("Location: pagina_restrita.php");
        exit;
    } else {
        $_SESSION['erro_login'] = "Email ou senha inválidos.";
        header("Location: login.php");
        exit;
    }
} catch (PDOException $e) {
    $_SESSION['erro_login'] = "Erro no servidor: " . $e->getMessage();
    header("Location: login.php");
    exit;
}
?>
				
			

4. cadastrar.php

				
					<?php
session_start();
require_once 'conexao.php';

$mensagem = "";
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
    $senha = filter_input(INPUT_POST, 'senha', FILTER_UNSAFE_RAW);
    $confirma = filter_input(INPUT_POST, 'confirma', FILTER_UNSAFE_RAW);

    if (!$email || !$senha || !$confirma) {
        $mensagem = "Preencha todos os campos!";
    } elseif ($senha !== $confirma) {
        $mensagem = "As senhas não conferem.";
    } else {
        // Checa se email já existe
        $stmt = $pdo->prepare("SELECT id FROM usuarios WHERE email = :email");
        $stmt->execute(['email' => $email]);
        if ($stmt->fetch()) {
            $mensagem = "Email já cadastrado.";
        } else {
            $senha_hash = password_hash($senha, PASSWORD_DEFAULT);
            $stmt = $pdo->prepare("INSERT INTO usuarios (email, senha) VALUES (:email, :senha)");
            if ($stmt->execute(['email' => $email, 'senha' => $senha_hash])) {
                $_SESSION['msg_sucesso'] = "Usuário cadastrado! Faça login.";
                header("Location: login.php");
                exit;
            } else {
                $mensagem = "Erro ao cadastrar, tente novamente.";
            }
        }
    }
}
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <title>Cadastrar usuário</title>
</head>
<body>
    <h2>Cadastro</h2>
    <?php if ($mensagem): ?>
        <p style="color:red;"><?php echo $mensagem; ?></p>
    <?php endif; ?>
    <form method="post">
        <label>Email:</label><br>
        <input type="email" name="email" required><br><br>
        <label>Senha:</label><br>
        <input type="password" name="senha" required><br><br>
        <label>Confirme a Senha:</label><br>
        <input type="password" name="confirma" required><br><br>
        <input type="submit" value="Cadastrar">
    </form>
    <p>Já possui cadastro? <a href="login.php">Entrar</a></p>
</body>
</html>>
				
			

5. pagina_restrita.php

				
					<?php
session_start();
// Protege a página: apenas se autenticado
if (!isset($_SESSION['autenticado']) || $_SESSION['autenticado'] !== true) {
    header("Location: login.php");
    exit;
}
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <title>Área Restrita</title>
</head>
<body>
    <h2>Bem-vindo(a), <?php echo htmlspecialchars($_SESSION['email_usuario']); ?>!</h2>
    <p>Você está em uma área restrita!</p>
    <a href="logout.php">Sair</a>
</body>
</html>
				
			

6. logout.php

				
					<?php
session_start();
// Limpa todos os dados da sessão
$_SESSION = [];
// Apaga o cookie de sessão
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}
session_destroy();
header("Location: login.php");
exit;
?>
				
			

7. Exemplo de SQL para a tabela de usuários

				
					CREATE TABLE usuarios (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(100) NOT NULL UNIQUE,
    senha VARCHAR(255) NOT NULL
);
				
			

Atenção:

Antes deste código funcionar, você precisa de um banco de dados meu_banco (ou o nome que preferir), uma tabela usuarios e pelo menos um usuário cadastrado com senha usando password_hash(). Exemplo de SQL:

				
					
-- Exemplo de registro com senha já criptografada:
INSERT INTO usuarios (email, senha) VALUES (
    'usuario@email.com',
    '$2y$10$wXxHj4v89MYFj5GdGZw1X.634GDRLb8oE6A3gKUpw9eKfRNL8vMiu'
);
-- A senha desse exemplo é: 123456
				
			

Você pode gerar senhas com o comando PHP:

				
					
echo password_hash('123456', PASSWORD_DEFAULT);
				
			

3.Esqueceu sua senha?

O procedimento será dividida em dois arquivos principais:

  • esqueci_senha.php – O usuário informa o email; sistema gera um token e mostra (simula o envio) o link de redefinição na tela.
  • redefinir_senha.php – O usuário acessa o link com o token e redefine sua senha, se o token for válido e não expirado.

Será incluso também as instruções SQL para alterar a tabela de usuários.

3.1. Nova Estrutura de Arquivos:

/
├── conexao.php
├── login.php
├── processa_login.php
├── pagina_restrita.php
├── logout.php
├── cadastrar.php
├── esqueci_senha.php # NOVO: formulário para pedir reset
├── redefinir_senha.php # NOVO: redefine a senha via token

3.2. SQL para estender a tabela de usuários

Antes, altere sua tabela de usuários para receber os campos de token de recuperação e vencimento:

				
					ALTER TABLE usuarios 
  ADD COLUMN token_recuperacao VARCHAR(64) DEFAULT NULL,
  ADD COLUMN token_expira_em DATETIME DEFAULT NULL;
				
			

3.3. esqueci_senha.php

Antes, altere sua tabela de usuários para receber os campos de token de recuperação e vencimento:

				
					<?php
session_start();
require_once 'conexao.php';

$msg = "";
$link_reset = "";

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);

    if (!$email) {
        $msg = "Informe um email válido.";
    } else {
        // Busca usuário
        $stmt = $pdo->prepare("SELECT id FROM usuarios WHERE email = :email LIMIT 1");
        $stmt->execute(['email' => $email]);
        $usuario = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($usuario) {
            // Gera token e prazo
            $token = bin2hex(random_bytes(32));
            $expira = date('Y-m-d H:i:s', strtotime('+30 minutes'));

            // Salva token no banco
            $stmt = $pdo->prepare("UPDATE usuarios SET token_recuperacao = :token, token_expira_em = :expira WHERE id = :id");
            $stmt->execute([
                'token' => $token, 
                'expira' => $expira, 
                'id' => $usuario['id']
            ]);

            // Link para redefinir
            $link_reset = "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF'])."/redefinir_senha.php?token=$token";
        }
        // Mensagem neutra para o usuário, sempre igual (boa prática)
        $msg = "Se o e-mail estiver cadastrado, você receberá instruções para redefinir sua senha.";
    }
}
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <title>Esqueci Minha Senha</title>
</head>
<body>
    <h2>Esqueceu sua senha?</h2>
    <?php if($msg): ?>
        <p style="color:green;"><?php echo $msg; ?></p>
    <?php endif; ?>
    <?php if($link_reset): ?>
        <p><strong>Simulação:</strong> Acesse o link a seguir para redefinir sua senha:<br>
        <a href="<?php echo $link_reset; ?>"><?php echo $link_reset; ?></a></p>
        <!-- Em produção, envie este link por email! -->
    <?php endif; ?>
    <form method="post">
        <label>E-mail cadastrado:</label> <br>
        <input type="email" name="email" required>
        <br><br>
        <input type="submit" value="Enviar redefinição">
    </form>
    <br>
    <a href="login.php">Voltar ao login</a>
</body>
</html>
				
			

3.4. redefinir_senha.php

				
					<?php
session_start();
require_once 'conexao.php';

$msg = "";
$formulario_ativo = false;

// Verifica se veio token (GET)
if (isset($_GET['token'])) {
    $token = $_GET['token'];

    // Busca usuário pelo token válido e expiração.
    $stmt = $pdo->prepare("SELECT id, token_expira_em FROM usuarios WHERE token_recuperacao = :token LIMIT 1");
    $stmt->execute(['token' => $token]);
    $usuario = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($usuario) {
        // Checa se token expirou
        if (strtotime($usuario['token_expira_em']) < time()) {
            $msg = "Token expirado. Solicite nova redefinição.";
        } else {
            $formulario_ativo = true; // Pode mostrar form de nova senha
        }
    } else {
        $msg = "Token inválido. Solicite nova redefinição.";
    }
} 

// Se envio do form de redefinição (POST)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['token'])) {
    $token = $_POST['token'];
    $nova = filter_input(INPUT_POST, 'nova', FILTER_UNSAFE_RAW);
    $confirma = filter_input(INPUT_POST, 'confirma', FILTER_UNSAFE_RAW);

    if (!$nova || !$confirma) {
        $msg = "Preencha todos os campos!";
        $formulario_ativo = true;
    } elseif ($nova !== $confirma) {
        $msg = "As senhas não conferem.";
        $formulario_ativo = true;
    } else {
        // Busca usuário pelo token e expiração de novo (por segurança)
        $stmt = $pdo->prepare("SELECT id, token_expira_em FROM usuarios WHERE token_recuperacao = :token LIMIT 1");
        $stmt->execute(['token' => $token]);
        $usuario = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($usuario && strtotime($usuario['token_expira_em']) >= time()) {
            // Atualiza senha e remove o token
            $hash = password_hash($nova, PASSWORD_DEFAULT);
            $stmt = $pdo->prepare("UPDATE usuarios SET senha = :senha, token_recuperacao = NULL, token_expira_em = NULL WHERE id = :id");
            $stmt->execute([
                'senha' => $hash,
                'id' => $usuario['id']
            ]);
            $msg = "<span style='color:green'>Senha redefinida com sucesso! Você pode <a href='login.php'>fazer login</a>.</span>";
        } else {
            $msg = "Token inválido ou expirado. Solicite nova redefinição.";
        }
    }
}
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <title>Redefinir Senha</title>
</head>
<body>
    <h2>Redefinir Senha</h2>
    <?php if($msg): ?>
        <p><?php echo $msg; ?></p>
    <?php endif; ?>

    <?php if($formulario_ativo): ?>
        <form method="post">
            <input type="hidden" name="token" value="<?php echo htmlspecialchars($token); ?>">
            <label>Nova Senha:</label><br>
            <input type="password" name="nova" required><br><br>
            <label>Confirme a Nova Senha:</label><br>
            <input type="password" name="confirma" required><br><br>
            <input type="submit" value="Redefinir senha">
        </form>
    <?php endif; ?>

    <br>
    <a href="login.php">Voltar ao login</a>
</body>
</html>
				
			

3.5. Adicione o link em login.php

Logo abaixo do formulário em login.php, insira:

				
					<p><a href="esqueci_senha.php">Esqueceu sua senha?</a></p>