Entrar em PHP

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:

Entrar em PHP

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.phppágina na publicpasta.

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.phppágina, você pode reutilizar os arquivos header.phpe footer.phpda src/incpasta e usar a view()função para carregá-los na login.phppá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.phpna srcpasta.

<?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.phppágina usando a técnica post-redirect-get (PRG) e defina o $errorse $inputsna 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 logine redirecione os usuários de volta à login.phppá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.phppá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 $inputse $errorsda 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.phpnecessá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 userstabela. 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 userstabela por nome de usuário, você pode definir uma função find_user_by_username()no src/auth.phparquivo:

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 userstabela, 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 usernamee passwordcorresponderem, você poderá fazer login do usuário. Para fazer isso, você precisa definir um valor no $_SESSIONexemplo:

$_SESSION['username'] = $username;Linguagem de código:  PHP  ( php )

Nas solicitações subsequentes, você pode verificar a $_SESSIONvariá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.phppá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 à $_SESSIONvariável. Portanto, você precisa removê-lo para desconectar o usuário.

O seguinte define a logout()função no auth.phpque desconecta um usuário removendo o usernamee user_idda $_SESSIONvariá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.phpna publicpasta.

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.phpe register.phpna srcpasta:


<?php

if (is_user_logged_in()) {
    redirect_to('index.php');
}Linguagem de código:  HTML, XML  ( xml )

O seguinte mostra login.phpna srcpasta:

<?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) à $_SESSIONvariável para marcar se um usuário está logado.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *