Inicios de sesión de Laravel Throttles
Quería compartir esta experiencia que ocurrió usando los inicios de sesión de Laravel Throttles y espero que al leer esto le ayude a evitar cometer los mismos errores.
Recientemente obtuve un nuevo requisito de los clientes para agregar valores de Política de contraseñas en los inicios de sesión, que incluyen:
Caducidad de la contraseña: le pedirá al usuario que restablezca su contraseña durante un conjunto determinado de días.
Forzar reinicio: para cuentas creadas por el administrador
Intentos máximos de contraseña incorrecta: para bloquear el reintento de contraseña durante un conjunto determinado de minutos
CADUCIDAD DE LA CONTRASEÑA
Esto se hizo usando una nueva tabla llamada “password_securities”con campos password_expiry_days and password_updated_at como se muestra a continuación:
Esto es bastante simple, dentro de LoginController simplemente agregue la lógica para verificar si la suma de password_updated_at y password_expiry_days es menor que la fecha actual como se muestra a continuación:
if($password_expiry_days != -1 && !is_null($password_expiry_days)){ if(isset($user) && !empty($user)){ $request->session()->forget('password_expired_id'); $password_updated_at = $user->passwordSecurity- >password_updated_at; $password_expiry_at = Carbon::parse($password_updated_at)- >addDays($password_expiry_days); if($password_expiry_at->lessThan(Carbon::now()) || $user->force_reset == "1"){ $request->session()- >put('password_expired_id',$user->id); auth()->logout(); return redirect('/passwordExpiration')- >with('error', "Your Password is expired, You need to change your password."); } } }
FORZAR RESET
Bastante simple aquí, acabamos de agregar un campo booleano “force_reset” en la tabla de usuarios y, si se establece en 1, el usuario debe cambiar la contraseña, como notará en el código anterior.
MÁXIMOS INTENTOS DE INICIO DE SESIÓN
Laravel vino con un paquete incorporado para Throttles Logins, solo era necesario agregar la siguiente línea de código dentro del LoginController:
if ($this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); return redirect('/login')->withErrors(array('error' => 'Your account has been disabled because of too many wrong attempts. Retry in '. $this->decayMinutes.' minutes')); } $this->incrementLoginAttempts($request);
Tenga en cuenta también que anulamos la variable global ‘decayMinutes’ que un usuario administrador configura dentro de las aplicaciones.
Se realizó el desarrollo y todo salió bien, incluso en nuestro servidor de desarrollo no se encontró el error…
Extraño, ¿no?
Después de horas de depuración, descubrí que el problema estaba en las direcciones IP
Como ya sabrá, la limitación de inicio de sesión en Laravel es una combinación del nombre de usuario y la dirección IP.
Por lo tanto, en la red privada del cliente, las direcciones IP se asignaron mediante NAT y la dirección IP externa sigue siendo la misma. Por lo tanto, si un solo usuario dentro de la empresa intenta erróneamente una contraseña, todos los demás usuarios tendrán que esperar un conjunto determinado de “decayMinutes” antes de poder intentar iniciar sesión nuevamente.
Afortunadamente, esto se puede personalizar en la configuración de autenticación de Laravel para usar solo el nombre de usuario y no una combinación de nombre de usuario y dirección IP, pero debe tener mucho cuidado aquí.
Esta configuración debe usarse solo en redes privadas ya que esto puede causar una amenaza a la seguridad. Un atacante puede intentar iniciar sesión en diferentes cuentas sin ningún tipo de limitación de velocidad llamado “ataque primero en amplitud”.
El siguiente código anula el método “throttleKey()” en LoginController:
protected function throttleKey(Request $request) { if (\Config::get('auth.throttle_key') == 'username') { return $request->email_username; }else if (\Config::get('auth.throttle_key') == 'ip') { return $request->ip(); }else { return Str::lower($request->input($this->username())).'|'.$request->ip(); } }
Y dentro de config / Auth.php se agregó la siguiente línea:
/* |--------------------------------------------------------------- | Throttle Key |--------------------------------------------------------------- | | You may choose to block ip address from failed attempts | of a combination of IP and Username | | Supported: "ip", "username|ip" | */ 'throttle_key' => 'username',
Ahora, los intentos máximos de inicio de sesión serán solo en nombre de usuario / correo electrónico y no en direcciones IP.
Espero que esto ayude a alguien en el futuro