Como criar caracteres aleatórios em aplicações Laravel usando Keygen

Laravel é um Framework PHP utilizado para o desenvolvimento web, que utiliza a arquitetura MVC e tem como principal característica ajudar a desenvolver aplicações seguras e performáticas de forma rápida, com código limpo e simples, já que ele incentiva o uso de boas práticas de programação e utiliza o padrão PSR-2 como guia para estilo de escrita do código.

No fim do ano passado, o Bugginho Developer entrevistou Diego Hernandes, um dos mais importantes movimentadores da comunidade Laravel no Brasil. Se você for um programador PHP e pensa em aprender a usar o Laravel, sugerimos que leia a entrevista para conhecer melhor este framework e sua comunidade no Brasil.

Algumas características proeminentes do Laravel são sua sintaxe simples e concisa, um sistema modular com gerenciador de dependencias dedicado, várias formas de acesso a banco de dados relacionais e vários utilitários indispensáveis no auxílio ao desenvolvimento e manutenção de sistemas.

Para ver o Laravel em ação, confira como a livecoder brasileira AGyrafa desenvolve um site com este framework:

Ao desenvolver aplicações, geralmente é comum ter a necessidade de criar caracteres aleatórios e, por isso, muitas linguagens de programação já têm mecanismos de geração aleatória embutidos. Algumas aplicações comuns incluem:

  • Geração de código numérico aleatório para confirmação de e-mail ou serviço de verificação de número de telefone;
  • Serviço de geração de senha que gera strings de senha alfanuméricas aleatórias;
  • Geração de tokens ou strings aleatórios codificados em Base64 como chaves API.

Quando seu aplicativo precisa gerar muitas sequências de caracteres como as enumeradas acima, então o pacote Keygen é uma boa opção.

O que é o Keygen?

Keygen é um pacote PHP para gerar sequências de caracteres aleatórios simples de qualquer comprimento desejado e é fornecido com quatro geradores, numérico, alfanumérico, token e bytes. Ele tem uma interface muito simples e suporta encadeamento de métodos, tornando possível gerar chaves aleatórias simples com apenas uma linha de código. O pacote Keygen pode poupar seu tempo ao implementar um mecanismo de geração aleatória personalizado para seu aplicativo. Aqui estão alguns benefícios adicionais do Keygen:

  • É muito fácil adicionar um prefixo ou sufixo à sequência gerada aleatoriamente;
  • Você pode processar a sequência gerada aleatoriamente através de uma fila de callables antes de ser finalmente produzida;
  • Você pode controlar manipulações e mutações de várias instâncias Keygen.

Vamos mostrar neste artigo como implementar o pacote Keygen e usá-lo em aplicações Laravel. Para obter uma documentação completa e guia de uso do pacote Keygen, consulte o documento README.

Começando

Neste tutorial, vamos criar um serviço simples de REST API. A API fornece endpoints para criar registros de usuário, mostrar o registro do usuário e gerar uma senha aleatória.

Este tutorial pressupõe que você já tem um aplicativo Laravel sendo executado e a ferramenta Composer já instalada em seu sistema e adicionada ao seu sistema PATH. Neste tutorial, vamos usar o Laravel 5.3. Você pode consultar o guia de instalação do Laravel se não tiver o Laravel instalado.

Em seguida, instalaremos o pacote Keygen como uma dependência para o nosso projeto usando composer. O pacote Keygen está disponível no repositório como gladcodes/keygen.

Se ele instalado corretamente, você verá uma tela como a seguinte imagem:

Criando um alias para o pacote do Keygen

A funcionalidade do pacote Keygen está encapsulada na classe KeygenKeygen. Por conveniência, registramos um alias para esta classe, para que possamos usá-lo facilmente em qualquer lugar em nossa aplicação. Para criar o alias, editamos o arquivo config/app.php e adicionamos um registro para nosso alias depois do último registro na array aliases, como mostrado a seguir.

// config/app.php

'aliases' => [
    // ... other alias records
    'Keygen' => KeygenKeygen::class,
],

Agora podemos usar o pacote Keygen em qualquer lugar em nossa aplicação. Adicione a diretiva use Keygen no seu código para usar o pacote Keygen como mostrado no exemplo a seguir.

// usage example

<?php

use Keygen;

$id = Keygen::numeric(10)->generate();
echo $id; //2542831057

Criando o Modelo do Usuário

Em seguida, vamos criar uma tabela de banco de dados chamada users para armazenar nossos registros de usuários. O esquema para a tabela é o seguinte:

  • id INT(11) NOT NULL PRIMARY
  • code CHAR(24) NOT NULL UNIQUE
  • firstname VARCHAR(32) NOT NULL
  • lastname VARCHAR(32) NOT NULL
  • email VARCHAR(80) NOT NULL UNIQUE
  • password_salt CHAR(64) NOT NULL
  • password_hash CHAR(60) NOT NULL

Se criada corretamente, ele deve ser como mostrado na captura de tela a seguir:

Antes de prosseguir, verifique o arquivo config/database.php e o arquivo .env do seu aplicativo para garantir que você tenha a configuração correta para seu banco de dados.

Em seguida, criaremos um modelo para a tabela users usando a interface de linha de comando artisan do Laravel. O Laravel já vem com  um modelo User interno e, por isso, temos que criar nosso modelo de usuário personalizado em um local diferente, a pasta app/Models, conforme mostrado no seguinte comando.

php artisan make:model Models/User

Modificaremos a classe User criada no arquivo app/Models/User.php conforme mostrado no código a seguir para configurar nosso modelo conforme necessário.

// app/Models/User.php

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

class User extends Model
{
    protected $table = 'users';

    public $timestamps = false;

    public $incrementing = false;

    public function setEmailAttribute($email)
    {
        // Ensure valid email
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new Exception("Invalid email address.");
        }

        // Ensure email does not exist
        elseif (static::whereEmail($email)->count() > 0) {
            throw new Exception("Email already exists.");
        }

        $this->attributes['email'] = $email;
    }
}

No código acima precedente, definimos a propriedade timestamps como false para desativar os recursos de timestamps do Laravel em nosso modelo. Também definimos a propriedade incrementing como false para desativar o incremento automático do campo da chave primária.

Finalmente, definimos um mutator para o atributo email do nosso modelo com verificação de validação de e-mail e verificação para evitar entradas de e-mail duplicadas.

Definindo rotas para a API

Em seguida, definiremos rotas para os endpoints da API. Existem basicamente quatro endpoints:

  • GET /api/users
  • POST /api/users
  • GET /api/user/{id}
  • GET /api/password
// routes/web.php
// Add the following route definitions for API

Route::group(['prefix' => 'api'], function() {
    Route::get('/users', 'ApiController@showAllUsers');
    Route::post('/users', 'ApiController@createNewUser');
    Route::get('/user/{id}', 'ApiController@showOneUser');
    Route::get('/password', 'ApiController@showRandomPassword');
});

Em seguida, criamos o nosso ApiController usando a interface de linha de comando artisan do Laravel e adicionamos os métodos registrados nas rotas.

php artisan make:controller ApiController

O comando acima cria um novo arquivo app/Http/Controllers/ApiController.php que contém a classe ApiController. Podemos ir em frente para editar a classe e adicionar os métodos registrados nas rotas.

// app/Http/Controllers/ApiController.php

<?php

namespace AppHttpControllers;

use IlluminateHttpRequest;

class ApiController extends Controller
{
    public function showAllUsers(Request $request)
    {}

    public function createNewUser(Request $request)
    {}

    public function showOneUser(Request $request, $id)
    {}

    public function showRandomPassword(Request $request)
    {}
}

O Laravel já vem com um middleware para verificação CSRF em todas as rotas web. Não exigiremos isso para a API, portanto, excluiremos nossas rotas api do serviço de verificação CSRF no arquivo app/Http/Middleware/VerifyCsrfToken.php.

// app/Http/Middleware/VerifyCsrfToken.php

<?php

namespace AppHttpMiddleware;

use IlluminateFoundationHttpMiddlewareVerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        '/api/*',
    ];
}

Gerando ID exclusivo para o usuário

O pacote Keygen será usado para gerar um ID inteiro de 8 dígitos para o usuário. Vamos implementar o mecanismo de geração de ID exclusivo em um novo método generateID(). Também adicionaremos diretivas de uso para classes Hash, Keygen e AppModelsUser em nosso controlador.

Primeiro, vamos adicionar um novo método generateNumericKey() para gerar chaves numéricas aleatórias de 8 dígitos de comprimento.

// app/Http/Controllers/ApiController.php

<?php

namespace AppHttpControllers;

use Hash;
use Keygen;
use AppModelsUser;
use IlluminateHttpRequest;

class ApiController extends Controller
{
    // ... other methods

    protected function generateNumericKey()
    {
        return Keygen::numeric(8)->generate();
    }
}

O pacote Keygen gera chaves numéricas chamando estaticamente o método numeric() da classe KeygenKeygen. É necessário um argumento length, que especifica o comprimento da chave numérica e assume como padrão 16 se omitido. No nosso caso, o comprimento da chave numérica gerada é 8. O método generate() deve ser chamado para retornar a chave gerada.

Geralmente, não é desejável ter números começando com zero armazenados no banco de dados, especialmente IDs. O snippet a seguir modifica o mecanismo de geração do método generateNumericKey() usando o método prefix() fornecido pelo pacote Keygen para adicionar um inteiro diferente de zero no início da chave numérica. Isso é conhecido como um afixo. O pacote Keygen também fornece um método suffix() para adicionar caracteres no final das chaves geradas.

// modified generateNumericKey() method
// Ensures non-zero integer at beginning of key

protected function generateNumericKey()
{
    // prefixes the key with a random integer between 1 - 9 (inclusive)
    return Keygen::numeric(7)->prefix(mt_rand(1, 9))->generate(true);
}

No código anterior, observe como chamamos numeric() com o comprimento 7. Isso ocorre porque estamos adicionando um inteiro aleatório não-zero como um prefixo, fazendo com que o comprimento da chave numérica gerada final seja 8 como é necessário.

E, agora, vamos implementar o método generateID() para gerar IDs de usuário exclusivo.

// generateID() method

protected function generateID()
{
    $id = $this->generateNumericKey();

    // Ensure ID does not exist
    // Generate new one if ID already exists
    while (User::whereId($id)->count() > 0) {
        $id = $this->generateNumericKey();
    }

    return $id;
}

Criando um novo usuário

Vamos escrever a implementação do método createNewUser() em nosso ApiController para criar um registro para o novo usuário.

public function createNewUser()
{
    $user = new User;

    // Generate unique ID
    $user->id = $this->generateID();

    // Generate code for user
    $user->code = $this->generateCode();

    // Collect data from request input
    $user->firstname = $request->input('firstname');
    $user->lastname = $request->input('lastname');
    $user->email = $request->input('email');

    $password = $request->input('password');

    // Generate random base64-encoded token for password salt
    $salt = Keygen::token(64)->generate();

    $user->password_salt = $salt;

    // Create a password hash with user password and salt
    $user->password_hash = Hash::make($password . $salt . str_rot13($password));

    // Save the user record in the database
    $user->save();

    return $user;
}

No fragmento anterior, usamos Keygen::token() para gerar um token aleatório de 64 bits codificado para a nossa senha salt, com 64 caracteres. Também usamos a fachada Hash incorporada do Laravel para fazer um hash de senha bcrypt usando a senha do usuário e a senha salt.

Agora você pode criar um registro de usuário através da rota POST/api/users. Aqui, usamos Postman para testar os endpoints da API. Esta é a carga JSON do meu pedido POST:

{
    "firstname": "Jack",
    "lastname": "Bauer",
    "email": "jackbauer@movie24.net",
    "password": "f1gHtTerr0rIsts"
}

Aqui, está uma imagem do Postman:

Implementando os métodos restantes

Vamos escrever a implementação dos métodos restantes em nosso controlador.

// app/Http/Controllers/ApiController.php

public function showAllUsers(Request $request)
{
    // Return a collection of all user records
    return User::all();
}

public function showOneUser(Request $request, $id)
{
    // Return a single user record by ID
    return User::find($id);
}

public function showRandomPassword(Request $request)
{
    // Set length to 12 if not specified in request
    $length = (int) $request->input('length', 12);

    // Generate a random alphanumeric combination
    $password = Keygen::alphanum($length)->generate();

    return ['length' => $length, 'password' => $password];
}

Na implementação do método showRandomPassword(), estamos usando o Keygen::alphanum() para criar uma combinação aleatória de caracteres alfanuméricos como a senha gerada. O comprimento da senha gerada é obtido a partir do parâmetro de consulta length da solicitação se for fornecido. Se não, o padrão é 12, como especificado.

Dr. Michael J. Garbade

I, Dr. Michael J. Garbade is the co-founder of the Education Ecosystem (aka LiveEdu), ex-Amazon, GE, Rebate Networks, Y-combinator. Python, Django, and DevOps Engineer. Serial Entrepreneur. Experienced in raising venture funding. I speak English and German as mother tongues. I have a Masters in Business Administration and Physics, and a Ph.D. in Venture Capital Financing. Currently, I am the Project Lead on the community project -Nationalcoronalvirus Hotline I write subject matter expert technical and business articles in leading blogs like Opensource.com, Dzone.com, Cybrary, Businessinsider, Entrepreneur.com, TechinAsia, Coindesk, and Cointelegraph. I am a frequent speaker and panelist at tech and blockchain conferences around the globe. I serve as a start-up mentor at Axel Springer Accelerator, NY Edtech Accelerator, Seedstars, and Learnlaunch Accelerator. I love hackathons and often serve as a technical judge on hackathon panels.

Recent Posts

Win Big with Our Amazon Fire Max 11 & AirPods Pro Giveaway!

We’re thrilled to announce an exciting opportunity for you to win not one but two…

1 month ago

Unleashing Potential: How Education Ecosystem Transforms Learning into Real-World Success

Acquiring practical skills is crucial for career advancement and personal growth. Education Ecosystem stands out…

3 months ago

The Role of Artificial Intelligence in Modern Software Development

Artificial Intelligence (AI) has been making significant strides in various industries, and the software development…

6 months ago

Highest Stable Coin Yields – (W16 – 2024)

Another week to bring you the top yield platforms for three of the most prominent…

7 months ago

LEDU Token OTC Trading

If you hold a large volume of LEDU tokens above 1 million units and wish…

8 months ago

Highest Stable Coin Yields – (W12 – 2024)

It’s another week and like always we have to explore the top yield platforms for…

8 months ago