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

Blockchain in Elections: A Leap Toward Transparent Democracy

In 2024 we're witnessing a critical point in democratic technology: the integration of blockchain and…

4 months ago

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…

6 months 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…

8 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…

11 months ago

Highest Stable Coin Yields – (W16 – 2024)

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

12 months ago

LEDU Token OTC Trading

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

1 year ago