Autenticação de usuário
1Introdução
Esta documentação explica passo a passo como configurar um sistema de autenticação sem senha em uma aplicação Temma.
O princípio é simples: o usuário digita seu endereço de email, recebe um link mágico por email, e ao clicar nele, é autenticado. O link só pode ser usado uma vez e expira após uma hora.
Esse sistema se baseia em dois componentes fornecidos pelo Temma:
- O controlador/plugin \Temma\Controllers\Auth: gerencia o formulário de login, o envio de emails e a sessão do usuário.
- O atributo \Temma\Attributes\Auth: restringe o acesso a controladores e ações com base na autenticação, nos papéis e nos serviços.
2Pré-requisitos
Para seguir este tutorial, você precisa de:
- Um projeto Temma funcionando (veja a página de Instalação).
- Um banco de dados MySQL ou MariaDB configurado em suas fontes de dados.
- Um servidor capaz de enviar emails (para os links mágicos).
3Criação do banco de dados
O sistema de autenticação requer duas tabelas: User (usuários) e AuthToken (tokens de conexão enviados por email).
Execute as seguintes consultas SQL para criar essas tabelas:
CREATE TABLE User (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
date_creation DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
date_last_login DATETIME,
date_last_access DATETIME,
email TINYTEXT CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
name TINYTEXT,
roles SET('admin', 'writer', 'reviewer'), -- deve ser personalizado
services SET('articles', 'news', 'images'), -- deve ser personalizado
PRIMARY KEY (id),
UNIQUE INDEX email (email(255))
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE TABLE AuthToken (
token CHAR(64) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL,
expiration DATETIME NOT NULL,
user_id INT UNSIGNED NOT NULL,
PRIMARY KEY (token),
INDEX expiration (expiration),
FOREIGN KEY (user_id) REFERENCES User (id) ON DELETE CASCADE
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
Os campos roles e services na tabela User são do tipo SET: você precisa personalizá-los de acordo com as necessidades da sua aplicação. Roles representam as funções do usuário (administrador, redator, etc.), e services representam os módulos aos quais eles têm acesso (artigos, imagens, etc.).
4Configuração
Você precisa configurar \Temma\Controllers\Auth tanto como um pré-plugin (para gerenciar a sessão do usuário a cada requisição) quanto como uma rota (para tornar o formulário de login acessível).
Adicione o seguinte ao seu arquivo etc/temma.php:
<?php
return [
'application' => [
'dataSources' => [
'db' => 'mysql://user:password@localhost/myDatabase'
]
],
'plugins' => [
'_pre' => [
'\Temma\Controllers\Auth'
]
],
'routes' => [
'auth' => '\Temma\Controllers\Auth'
]
];
- Linhas 5 a 7: configuração da conexão com o banco de dados (adapte ao seu ambiente).
- Linhas 10 a 12: declaração do pré-plugin. A cada requisição, ele verifica se o usuário está autenticado e disponibiliza suas informações.
- Linhas 14 a 16: declaração da rota. O controlador ficará acessível pelas URLs /auth/login e /auth/logout.
5Personalizando o template de login
O controlador Auth usa um template Smarty localizado em templates/auth/login.tpl. A versão fornecida pelo Temma é mínima; recomendamos que você crie sua própria versão.
Aqui está um exemplo de template de formulário de login:
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
{if $authError}
<p style="color: red;">Endereço de email desconhecido.</p>
{/if}
{if $authSent}
<p style="color: green;">
Um link de login foi enviado para o seu endereço de email.
Verifique sua caixa de entrada.
</p>
{else}
<form method="post" action="/auth/login">
<label for="email">Endereço de email:</label>
<input type="email" id="email" name="email" required />
<button type="submit">Entrar</button>
</form>
{/if}
</body>
</html>
- Linha 7: se o endereço de email não for encontrado no banco de dados, uma mensagem de erro é exibida.
- Linha 10: se o email for enviado com sucesso, uma mensagem de confirmação é exibida no lugar do formulário.
- Linhas 16 a 19: o formulário envia o endereço de email via POST para /auth/login.
6Testando o login
Antes de testar, certifique-se de ter pelo menos um usuário no banco de dados. Você pode inserir um manualmente:
INSERT INTO User (email, name) VALUES ('john@example.com', 'John');
O processo de login funciona da seguinte forma:
- Acesse /auth/login no seu navegador.
- Digite o endereço de email do usuário e envie o formulário.
- Um email contendo um link de login é enviado para esse endereço.
- Ao clicar no link, o usuário é autenticado e redirecionado para a página inicial.
O link de login é de uso único e expira após uma hora.
7Protegendo páginas com o atributo Auth
O atributo Auth restringe o acesso a controladores ou ações com base na autenticação. Ele depende da variável de template $currentUser definida pelo pré-plugin.
Para proteger um controlador inteiro (todas as suas ações exigem autenticação):
use \Temma\Attributes\Auth as TµAuth;
#[TµAuth]
class Account extends \Temma\Web\Controller {
public function profile() {
// acessível apenas a usuários autenticados
}
public function settings() {
// idem
}
}
Para proteger apenas ações específicas:
use \Temma\Attributes\Auth as TµAuth;
class Blog extends \Temma\Web\Controller {
// acessível a todos
public function list() { }
// restrito a usuários com o papel "writer"
#[TµAuth('writer')]
public function create() { }
// restrito a usuários com acesso ao serviço "images"
#[TµAuth(service: 'images')]
public function uploadImage() { }
// restrito a usuários com o papel "admin" ou "writer"
#[TµAuth(['admin', 'writer'])]
public function edit() { }
}
Se um usuário não autorizado tentar acessar uma página protegida, ele recebe um erro HTTP 401 por padrão. Para redirecioná-lo ao formulário de login, adicione esta configuração ao etc/temma.php:
<?php
return [
'x-security' => [
'authRedirect' => '/auth/login'
]
];
Para armazenar a URL solicitada de modo que o usuário seja redirecionado a ela após o login, use o parâmetro storeUrl:
use \Temma\Attributes\Auth as TµAuth;
#[TµAuth(redirect: '/auth/login', storeUrl: true)]
class Account extends \Temma\Web\Controller {
// ...
}
Dessa forma, após efetuar o login, o usuário será redirecionado para a página que estava tentando acessar.
8Usando informações do usuário
O pré-plugin Auth fornece duas variáveis de template, acessíveis em templates, controladores e plugins:
- currentUserId: identificador do usuário autenticado (ou null se não autenticado).
- currentUser: dados do usuário (array associativo contendo as chaves id, email, name, roles, services, etc.).
Aqui está um exemplo de uso em um template Smarty:
{if $currentUserId}
<p>Olá, {$currentUser.name}!</p>
{if $currentUser.roles.admin}
<a href="/admin">Administração</a>
{/if}
<a href="/auth/logout">Logout</a>
{else}
<a href="/auth/login">Login</a>
{/if}
Em um controlador, essas variáveis são acessíveis via $this['currentUserId'] e $this['currentUser']:
class Account extends \Temma\Web\Controller {
public function profile() {
$userId = $this['currentUserId'];
$user = $this['currentUser'];
$this['userName'] = $user['name'];
$this['isAdmin'] = $user['roles']['admin'] ?? false;
}
}
9Logout
Para desconectar um usuário, redirecione-o para a URL /auth/logout. Ele será automaticamente redirecionado para a página inicial após o logout.
Exemplo de link de logout em um template:
<a href="/auth/logout">Logout</a>
Se você quiser redirecionar o usuário para uma URL específica após o login (e, portanto, também após o logout e um novo login), configure o parâmetro redirection (veja a seção Configuração avançada).
10Configuração avançada
Todas as opções de configuração ficam sob a chave x-security > auth no arquivo etc/temma.php.
Personalização do email
Você pode personalizar o remetente, o assunto e o conteúdo do email de login:
<?php
return [
'x-security' => [
'auth' => [
'emailSender' => 'no-reply@mysite.com',
'emailSubject' => 'Your login link',
'emailText' => "Hi,\n\nHere is your login link:\n%s\n\nIt is valid for 1 hour.\n\nBest regards"
]
]
];
O marcador %s no texto é substituído pela URL de login.
Registro automático
Por padrão, apenas os usuários já presentes no banco de dados podem fazer login. Para registrar automaticamente novos usuários:
<?php
return [
'x-security' => [
'auth' => [
'registration' => true
]
]
];
Redirecionamento após o login
Por padrão, o usuário é redirecionado para a página inicial após o login. Você pode alterar essa URL:
<?php
return [
'x-security' => [
'auth' => [
'redirection' => '/my-account'
]
]
];
Observe que, se o atributo Auth tiver armazenado a URL solicitada (parâmetro storeUrl), ela será usada em seu lugar.
Personalização de nomes de tabelas e campos
Se suas tabelas ou campos tiverem nomes diferentes dos padrões, você pode redefini-los:
<?php
return [
'x-security' => [
'auth' => [
'userData' => [
'base' => 'auth_db',
'table' => 'tUser',
'id' => 'user_id',
'email' => 'user_mail',
'roles' => 'user_roles',
'services' => 'user_services',
],
'tokenData' => [
'base' => 'auth_db',
'table' => 'tToken',
'token' => 'token_hash',
'expiration' => 'expiration_date',
'user_id' => 'fk_user_id',
]
]
]
];
Para mais detalhes sobre todas as opções de configuração, consulte a documentação completa do controlador/plugin Auth e do atributo Auth.