login personalizado laravel

Laravel nos ofrece un sistema de autenticación predeterminado que podemos generar de una forma muy práctica con solo ejecutar el comando php artisan make:auth Este comando trabaja utilizando el modelo User que Laravel trae por defecto y la tabla users que puede ser generada ejecutando las migraciones que se incluyen con la instalación del framework.  Sin embargo, en ocasiones puede presentarse el caso de que un proyecto tenga una base de datos que ya se encuentre en producción o que no cumpla con la estructura que maneja Laravel por defecto.

Hace poco se me presentó la situación en la que no podía utilizar directamente la tabla users de Laravel, ni tampoco los campos email y password que el modelo User utiliza para iniciar sesión.  Adicionalmente, tampoco podía utilizar la encriptación que trae Laravel, la cual se basa en bcrypt, sino que las contraseñas tenían que ser encriptadas utilizando MD5.

Por lo que la forma más práctica que conseguí fue crear un login personalizado para manejar esto. Si en algún momento se te presenta esta situación no hay de que preocuparse, nuestro framework favorito es muy flexible y nos permite aplicar accesos personalizados sin perder la potencialidad que nos brinda.

Instalar el login por defecto de Laravel

Para personalizar el inicio de sesión de la aplicación trabajaremos en función del que trae de manera predeterminada, así que si no lo tienes ya instalado entonces solo debes dirigirte a una terminal, ubicarte en el proyecto y ejecutar el comando:

php artisan make:auth

Esto generará todo el scaffolding completo de un sistema de autenticación: Login, Registro y Recuperación de contraseña. Adicionalmente, creará las vistas y métodos correspondientes para ejecutar cada una de estas funcionalidades y de las cuales haremos uso durante este tutorial.

Cambiar de email a username

Puede darse el caso que necesites cambiar la forma en cómo los usuarios se identifican cuando se conectan para que en vez de usar su correo electrónico utilice un username o alias.

Para ello, es necesario sobrescribir el método username del trait AuthenticateUsers de Laravel, el cual se encuentra en:

\vendor\laravel\framework\src\Illuminate\Foundation\Auth

Dentro de dicho método indicamos cómo se llamará el campo de la base de datos para identificar y dar acceso en el formulario de login. Lo vamos a sobrescribir agregando el siguiente método a la clase app/Http/Controllers/Auth/LoginController.php:

/**
* Check either username or email.
* @return string
*/
public function username()
{
    return 'nombre_de_usuario_o_correo_personalizado_aqui';
}

Cambiar campo password

También puede ocurrir que en la aplicación que estamos trabajando el campo de la tabla de usuarios en la base de datos para guardar la contraseña se llame diferente al que usa Laravel inicialmente. Por defecto este campo se llama password.

Para hacer el cambio, debemos indicarle a Laravel en nuestro modelo de usuarios App\User cómo se llama el campo correspondiente a la contraseña en nuestra tabla de usuarios, sobrescribiendo el método getAuthPassword, para que devuelva el nombre del verdadero campo que maneja la contraseña: 

<?php
public function getAuthPassword()
{
    return $this->nombre_de_campo_de_contrasena_personalizado_aqui;
}

getAuthPassword es un método perteneciente al trait Illuminate\Auth\Authenticatable el cual se encarga de darle facultades al modelo User para que el usuario se pueda autenticar.

Cambiar la forma de validar las credenciales

Como dije anteriormente quiero cambiar que la encriptación de las contraseñas de los usuarios se haga usando MD5.

Para resolver esta situación, hay que entender cómo funciona la autenticación. Laravel usa implementaciones de la interfaz Illuminate\Contracts\Auth\UserProvider para recuperar una implementación de Illuminate\Contracts\Auth\Authenticatable de un sistema de almacenamiento persistente. De esta manera los mecanismos de autenticación de Laravel funcionan independientemente de cómo se almacenen los datos del usuario o qué tipo de clase se usa para representarlo.

Por defecto, Laravel usa la implementación Illuminate\Auth\EloquentUserProvider para autenticar haciendo uso de Eloquent y el modelo User.

En esta clase tiene entre sus métodos a validateCredentialsque se encarga de validar el usuario con respecto a las credenciales dadas, es decir, compara la contraseña ingresada desde el formulario de acceso con una encriptada en la tabla de usuarios de la base de datos.

Con el propósito de sobrescribir la funcionalidad que trae originalmente dicho método, necesitamos crea un EloquentUserProvider personalizado. Para ello creamos una nueva clase llamada MyEloquentUserProvider en el directorio app en mi caso la agregué dentro de un directorio llamado Extensions. Esta debe extender de EloquentUserProvider.

Copiamos el método validateCredentials deEloquentUserProvidery lo pegamos como un método en nuestra clase personalizada, para que compare las contraseñas encriptadas con MD5 en vez de bcrypt que es la forma por defecto que utiliza Laravel retornando true o false según sea el caso.

Es importante señalar que dentro de lo posible no deberías reemplazarse la encriptación por defecto que trae Laravel por el uso de MD5. Este es un método mucho menos seguro y nada óptimo en comparación.

<?php
namespace App\Extensions;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;

class MyEloquentUserProvider extends EloquentUserProvider
{
    /**
     * Validate a user against the given credentials.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable  $user
     * @param  array  $credentials
     * @return bool
     */
    public function validateCredentials(UserContract $user, array $credentials)
    {
        $plain = $credentials['password'];
        $hashed_value = $user->getAuthPassword();
        return $hashed_value == md5($plain);
    }
}

De igual forma podemos sobrescribir cualquier otro método que pertenezca a esta clase si lo copiamos en la clase creada previamente por nosotros.

Registrar el nuevo provider en AuthServiceProvider

Debemos agregar el nuevo provider MyEloquentUserProvider en AuthServiceProviderel cual se encuentra en el directorio App\Providers esto se hace para que Laravel pueda ubicar y utilizar la lógica que hayamos escrito dentro de él:

<?php

namespace App\Providers;
use App\Extensions\MyEloquentUserProvider;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Auth::provider('custom_user', function ($app, array $config) {
            $model = $app['config']['auth.providers.users.model'];
            return new MyEloquentUserProvider($app['hash'], $model);
        });
    }
}

Lo que hemos hecho es dentro del método boot llamar al Facade Auth::providerel cual recibe dos parámetros: el nombre del provider (definido por ti) y una función callback que recibe una instancia de la variable app  y el array de configuraciones que trae Laravel. Asignamos en una variable la llave de configuración  y retornamos una instancia de ésta. Así cuando un usuario intente acceder a la aplicación se activará este método y buscará la instancia del mismo para comparar las credenciales.

Registrar nuestro provider en el directorio de config

Solo queda decirle a Laravel que utilice el nuevo provider en vez del que trae por defecto. Para ello nos dirigimos al archivo auth.phpque se encuentra en el directorio configy nos ubicamos en el array de providers:

<?php
'providers' => [
    'custom' => [
        'driver' => 'custom_user',
        'model' => App\User::class,
    ],
    'users' => [
        'driver' => 'eloquent',            
        'model' => App\User::class,            
    ],
],

Aquí creamos la llave para nuestro provider y le damos el nombre que deseemos (custom en este caso), en la llave driver debemos asignar el nombre que hayamos escrito en Auth::provider dentro del método boot en AuthServiceProvider (en nuestro caso custom_user). Adicionalmente, le pasamos el modelo de usuarios que estemos utilizando (en nuestro caso es el mismo que trae Laravel por defecto) e incluso de ser necesario pudiésemos asignarle la tabla de usuarios en la base de datos en la que queramos que busque las credenciales suponiendo no sea la misma que utiliza Laravel:

<?php
'custom' => [
    'driver' => 'custom_user',
    'model' => App\User::class,
    'table' => 'usuarios',
],

En este mismo archivo subimos un poco y agregamos en el arreglo guards el nuevo provider:

<?php
'guards' => [
    'custom' => [
        'driver' => 'session',
        'provider' => 'custom',
    ],

    'web' => [
        'driver' => 'session',            
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'token',
        'provider' => 'users',
    ],
],

Y ya por último al inicio del archivo definimos cuál es el guard que utilizará por defecto:

<?php
'defaults' => [
    'guard' => 'custom',
    'passwords' => 'users',
],

¡Listo! de esta forma podemos agregar nuestras propias validaciones en nuestra aplicación con Laravel e incluso podemos extender la validación por defecto que el framework nos ofrece y así personalizar el acceso a nuestro sistema.

Material relacionado

Suscríbete a nuestro boletín

Te enviaremos publicaciones con consejos útiles y múltiples recursos para que sigas aprendiendo.

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.