Resumo : neste tutorial, você aprenderá como criar um formulário de login usando nome de usuário e senha.
Pré-requisitos
Para iniciar este tutorial, você precisa concluir o tutorial anterior que cria um formulário de registro .
Introdução ao formulário de login PHP
No tutorial anterior, você aprendeu como criar um formulário que permite aos usuários se cadastrarem em contas . Depois que os usuários se registrarem com sucesso, você os redirecionará para a página de login para que possam usar seus nomes de usuário e senhas para fazer login.
A página de login conterá um formulário que consiste nas entradas de nome de usuário e senha e um botão de login como segue:
Para fazer login, os usuários precisam inserir seu nome de usuário e senha e clicar no botão de login.
Se o nome de usuário e a senha corresponderem, você poderá redirecioná-los para uma página protegida por senha. Caso contrário, você redirecionará os usuários de volta à página de login com uma mensagem de erro:
Observe que é mais seguro emitir uma mensagem genérica (nome de usuário ou senha inválidos) quando o nome de usuário ou a senha não correspondem.
Crie o formulário de login
Primeiro, crie a login.php
página na public
pasta.
Segundo, defina um formulário de login com o nome de usuário e senha e um botão de login:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://tutorials.acervolima.com/app/css/style.css">
<title>Login</title>
</head>
<body>
<main>
<form action="login.php" method="post">
<h1>Login</h1>
<div>
<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>
<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<section>
<button type="submit">Login</button>
<a href="register.php">Register</a>
</section>
</form>
</main>
</body>
</html>
Linguagem de código: HTML, XML ( xml )
Assim como a register.php
página, você pode reutilizar os arquivos header.php
e footer.php
da src/inc
pasta e usar a view()
função para carregá-los na login.php
página da seguinte maneira:
<?php
require __DIR__ . '/../src/bootstrap.php';
?>
<?php view('header', ['title' => 'Login']) ?>
<main>
<form action="login.php" method="post">
<h1>Login</h1>
<div>
<label for="username">Username:</label>
<input type="text" name="username" id="username">
</div>
<div>
<label for="password">Password:</label>
<input type="password" name="password" id="password">
</div>
<section>
<button type="submit">Login</button>
<a href="register.php">Register</a>
</section>
</form>
</main>
<?php view('footer') ?>
Linguagem de código: PHP ( php )
O formulário de login é enviado para login.php
. Portanto, você pode verificar se o método de solicitação HTTP é POST antes de processar o formulário.
Para processar o formulário, você cria o arquivo login.php
na src
pasta.
<?php
$inputs = [];
$errors = [];
if (is_post_request()) {
[$inputs, $errors] = filter($_POST, [
'username' => 'string | required',
'password' => 'string | required'
]);
if ($errors) {
redirect_with('login.php', ['errors' => $errors, 'inputs' => $inputs]);
}
// if login fails
if (!login($inputs['username'], $inputs['password'])) {
$errors['login'] = 'Invalid username or password';
redirect_with('login.php', [
'errors' => $errors,
'inputs' => $inputs
]);
}
// login successfully
redirect_to('index.php');
} else if (is_get_request()) {
[$errors, $inputs] = session_flash('errors', 'inputs');
}
Linguagem de código: PHP ( php )
Como funciona.
Primeiro, defina duas variáveis para armazenar os dados limpos e as mensagens de erro:
$inputs = [];
$errors = [];
Linguagem de código: PHP ( php )
Segundo, verifique se o método de solicitação HTTP é POST usando a is_post_request()
função:
if (is_post_request()) {
// ...
}
Linguagem de código: PHP ( php )
Terceiro, limpe e valide as entradas do usuário usando a filter()
função:
[$inputs, $errors] = filter($_POST, [
'username' => 'string | required',
'password' => 'string | required'
]);
Linguagem de código: PHP ( php )
Quarto, se o nome de usuário ou a senha não forem fornecidos, redirecione os usuários para a login.php
página usando a técnica post-redirect-get (PRG) e defina o $errors
e $inputs
na sessão usando a redirect_with()
função.
if ($errors) {
redirect_with('login.php', [
'errors' => $errors,
'inputs' => $inputs
]);
}
Linguagem de código: PHP ( php )
Quinto, chame a login()
função para verificar o nome de usuário e a senha.
Se o nome de usuário ou a senha não corresponderem, defina uma mensagem de erro com a chave login
e redirecione os usuários de volta à login.php
página:
<?php
if (!login($inputs['username'], $inputs['password'])) {
$errors['login'] = 'Invalid username or password';
redirect_with('login.php', [
'errors' => $errors,
'inputs' => $inputs
]);
}
Linguagem de código: PHP ( php )
Sétimo, se o nome de usuário e a senha corresponderem, redirecione os usuários para a index.php
página:
redirect_to('index.php');
Linguagem de código: PHP ( php )
Esta index.php
é a página protegida por senha. Isso significa que apenas usuários logados podem acessá-lo – mais sobre isso na próxima seção.
Por fim, obtenha $inputs
e $errors
da sessão se o método de solicitação HTTP for GET.
[$errors, $inputs] = session_flash('errors', 'inputs');
Linguagem de código: PHP ( php )
Mostrar os dados inseridos e a mensagem de erro na página login.php
É public/login.php
necessário mudar para o seguinte para mostrar as entradas do usuário, bem como as mensagens de erro:
<?php
require __DIR__ . '/../src/bootstrap.php';
require __DIR__ . '/../src/login.php';
?>
<?php view('header', ['title' => 'Login']) ?>
<?php if (isset($errors['login'])) : ?>
<div class="alert alert-error">
<?= $errors['login'] ?>
</div>
<?php endif ?>
<form action="login.php" method="post">
<h1>Login</h1>
<div>
<label for="username">Username:</label>
<input type="text" name="username" id="username" value="<?= $inputs['username'] ?? '' ?>">
<small><?= $errors['username'] ?? '' ?></small>
</div>
<div>
<label for="password">Password:</label>
<input type="password" name="password" id="password">
<small><?= $errors['password'] ?? '' ?></small>
</div>
<section>
<button type="submit">Login</button>
<a href="register.php">Register</a>
</section>
</form>
<?php view('footer') ?>
Linguagem de código: PHP ( php )
Como a login()
função não existe, precisamos defini-la.
Defina a função login()
A login()
função aceita nome de usuário e senha e retorna verdadeiro se forem válidos. A lógica da login()
função é a seguinte:
- Primeiro, encontre o nome de usuário na
users
tabela. Se o usuário existir, vá para a etapa 2. - Segundo, verifique se a senha corresponde.
- Terceiro, se o nome de usuário não existir ou a senha não corresponder, emita uma mensagem de erro.
Para encontrar um usuário na users
tabela por nome de usuário, você pode definir uma função find_user_by_username()
no src/auth.php
arquivo:
function find_user_by_username(string $username)
{
$sql = 'SELECT username, password
FROM users
WHERE username=:username';
$statement = db()->prepare($sql);
$statement->bindValue(':username', $username, PDO::PARAM_STR);
$statement->execute();
return $statement->fetch(PDO::FETCH_ASSOC);
}
Linguagem de código: PHP ( php )
Se existir um nome de usuário na users
tabela, a find_user_by_username()
função retorna um array associativo com dois elementos cujas chaves são nome de usuário e senha. Caso contrário, retorna falso.
Como você armazena o hash da senha no banco de dados, você precisa usar a função integrada password_verify()
para combinar a senha simples com um hash.
A password_verify()
função retorna verdadeiro se uma senha de texto simples corresponder a um hash, ou falso caso contrário.
Se ambos username
e password
corresponderem, você poderá fazer login do usuário. Para fazer isso, você precisa definir um valor no $_SESSION
exemplo:
$_SESSION['username'] = $username;
Linguagem de código: PHP ( php )
Nas solicitações subsequentes, você pode verificar a $_SESSION
variável para ver se o usuário com nome de usuário está logado no momento.
// check if the username has been logged in
if(isset($_SESSION['username'])) {
// already logged in
// ...
}
Linguagem de código: PHP ( php )
Aqui está a login()
função completa:
function login(string $username, string $password): bool
{
$user = find_user_by_username($username);
// if user found, check the password
if ($user && password_verify($password, $user['password'])) {
// prevent session fixation attack
session_regenerate_id();
// set username in the session
$_SESSION['username'] = $user['username'];
$_SESSION['user_id'] = $user['id'];
return true;
}
return false;
}
Linguagem de código: PHP ( php )
Observe que você deve chamar a session_regenerate_id()
função para gerar novamente um novo ID de sessão quando os usuários começarem a fazer login. Isso ajuda a evitar o ataque de fixação de sessão.
O seguinte define a is_user_logged_in()
função no arquivo src/auth.php, que retorna verdadeiro se um usuário estiver logado no momento:
function is_user_logged_in(): bool
{
return isset($_SESSION['username']);
}
Linguagem de código: PHP ( php )
Se os usuários não estiverem logados, você pode redirecioná-los para a página login.php. A seguir define a require_login()
função que redireciona para a página login.php se o usuário atual não estiver logado:
function require_login(): void
{
if (!is_user_logged_in()) {
redirect_to('login.php');
}
}
Linguagem de código: PHP ( php )
E você pode chamar a require_login()
função no início de qualquer página que exija login.
Por exemplo, você pode chamá-lo na public/index.php
página assim:
<?php
require __DIR__ . '/../src/bootstrap.php';
require_login();
?>
Linguagem de código: PHP ( php )
Desconectar um usuário
Para desconectar um usuário, você precisa remover o valor definido quando conectado e redirecionar para a página login.php.
Na login()
função, você adiciona o nome de usuário à $_SESSION
variável. Portanto, você precisa removê-lo para desconectar o usuário.
O seguinte define a logout()
função no auth.php
que desconecta um usuário removendo o username
e user_id
da $_SESSION
variável:
function logout(): void
{
if (is_user_logged_in()) {
unset($_SESSION['username'], $_SESSION['user_id']);
session_destroy();
redirect_to('login.php');
}
}
Linguagem de código: PHP ( php )
O seguinte define a current_user()
função que retorna o nome de usuário do usuário conectado no momento:
function current_user()
{
if (is_user_logged_in()) {
return $_SESSION['username'];
}
return null;
}
Linguagem de código: PHP ( php )
Crie o link de logout
Quando os usuários fazem login com êxito, eles são redirecionados para o arquivo index.php
.
No index.php
, você pode mostrar uma mensagem de boas-vindas, bem como um link de logout como este:
<?php
require __DIR__ . '/../src/bootstrap.php';
require_login();
?>
<?php view('header', ['title' => 'Dashboard']) ?>
<p>Welcome <?= current_user() ?> <a href="logout.php">Logout</a></p>
<?php view('footer') ?>
Linguagem de código: PHP ( php )
Quando os usuários clicam no link de logout, você precisa chamar a logout()
função para desconectar os usuários.
Para fazer isso, você precisa criar o arquivo logout.php
na public
pasta.
No logout.php
, você precisa chamar a logout()
função da seguinte maneira:
<?php
require __DIR__ . '/../src/bootstrap.php';
logout();
Linguagem de código: PHP ( php )
Redirecionar se os usuários já estiverem logados
Se os usuários já estiverem logados e navegarem para a página login.php ou Register.php, você precisará redirecioná-los para index.php.
Para fazer isso, você pode adicionar o seguinte código ao início do arquivo login.php
e register.php
na src
pasta:
<?php
if (is_user_logged_in()) {
redirect_to('index.php');
}
Linguagem de código: HTML, XML ( xml )
O seguinte mostra login.php
na src
pasta:
<?php
if (is_user_logged_in()) {
redirect_to('index.php');
}
$inputs = [];
$errors = [];
if (is_post_request()) {
// sanitize & validate user inputs
[$inputs, $errors] = filter($_POST, [
'username' => 'string | required',
'password' => 'string | required'
]);
// if validation error
if ($errors) {
redirect_with('login.php', [
'errors' => $errors,
'inputs' => $inputs
]);
}
// if login fails
if (!login($inputs['username'], $inputs['password'])) {
$errors['login'] = 'Invalid username or password';
redirect_with('login.php', [
'errors' => $errors,
'inputs' => $inputs
]);
}
// login successfully
redirect_to('index.php');
} else if (is_get_request()) {
[$errors, $inputs] = session_flash('errors', 'inputs');
}
Linguagem de código: HTML, XML ( xml )
Resumo
- Use a
password_verify()
função para verificar a senha. - Chame a
session_regenerate_id()
função para evitar o ataque de fixação de sessão. - Adicione um ou mais valores (nome de usuário e idl do usuário) à
$_SESSION
variável para marcar se um usuário está logado.