En este tip de Laravel vamos a ver una gran forma de hacer rutas más seguras tanto como para sitios web, como para APIs que expongamos de nuestra aplicación.
Pongamos el caso de las rutas que definimos para la actualización de registramos. Estamos acostumbrados a ver ejemplos de esta forma:
Route::post('product/{id}', 'ProductController@update');
Y luego, en el controlador:
class ProductController extends Controller { public function update(Product $id) { //... } }
El problema con esto es que no estamos validando que es $id
, suponemos que será un numero entero pero ¿qué pasaría si alguna persona ingresa en la url un valor no numérico?, ¿lo tenemos contemplado?, ¿cómo responderíamos en ese caso?. Son algunas preguntas importantes que debemos tener en cuenta para tener una aplicación más segura y robusta.
Método where() para rutas más seguras
Como estamos acostumbrados, Laravel ya ha pensado en eso y nos brinda el método where()
para filtrar los parámetros que están siendo enviados en la url.
El método where()
de Route nos permite definir que valores podrá tomar cada uno de los parámetros que definimos en las rutas. Veamos como sería para el ejemplo anterior:
Route::post('product/{id}', 'ProductController@update')->where('id', '[0-9]+');
Como vemos, el primer argumento es el nombre que le dimos al parámetro de la url. Y el segundo argumento, es una expresión regular.
Para este caso, estamos diciendo que {id}
solo podrá contener números enteros. En caso no sea así, automáticamente el sistema mostrará el error 404.
En la documentación oficial de Laravel podes ver más ejemplos de como utilización.
Si llegarás a tener más parámetros en la ruta, entonces debemos definir los filtros para cada parámetro con un arreglo:
Route::get('product/{id}/title/{title}', 'ProductController@show')->where([ 'id' => '[0-9]+', 'title' => '[a-z]+' ]);
¿Y si solo quieres que el parámetro tome ciertos valores? También lo podes hacer con una expresión como esta:
Route::get('product/{status}', 'ProductController@index')->where('status', 'approved|draft');
De esta forma nos aseguramos que los parámetros sean los que esperamos o del tipo que esperamos. Simplemente, genial 👏.
Pero esto no termina acá, tengo un truco más para comentarte.
Definición global de filtros para las rutas
No es necesario que estemos especificando en cada ruta que valores podrá contener los parámetros.
Si siempre repetimos, por ejemplo, que las rutas que tienen el parámetro {id}
deben ser un valor comprendido entre 0 y 9 (con la expresión regular [0-9]+
), podemos simplificar esto haciendo una definición global. Veamos como hacerlo.
Debemos editar el archivo app/Providers/RouteServiceProvider.php de la siguiente manera:
public function boot() { Route::pattern('id', '[0-9]+'); parent::boot(); }
De esta forma, le estamos diciendo a Laravel que siempre que utilicemos {id}
en alguna de nuestras rutas, verifique si el valor esta comprendido entre 0 y 9. Sin la necesidad de utilizar la función where()
para esas rutas 😉.
Espero que les haya gustado este Laravel Tip. Si fue así, deja un comentario y no te olvides de compartirlo en tus redes sociales. Nos vemos!
Magnífico tip, ahora a implementar y aprovechar para hacer nuestros desarrollo más poderosos
Excelente, muy bien explicado
Que buenos consejos. Mil gracias
Excelente, me encanta este sitio.
Muchas gracias a vos por tu comentario.
Pregunta:
No debería ser: Route::pattern(‘id’, ‘^[0-9]+$’);
No, no hace falta marcar el principio y fin de la cadena. Saludos.
Gracias!
Y si deseo hacerlo con id encriptados
Hola Josué, como estas? No te haría ponerle mas seguridad si ya envías el id encriptado.
Es importante que usted realice hash de las contrasenas correctamente antes de almacenarlos. Una vez realizado el hash a la contrasena con una funcion aplicada contra la contrasena del usuario, el paso es irreversible. Esto produce una cadena de longitud fija que no puede ser revertida factiblemente. Esto significa que puede comparar un hash contra otro para determinar si ambos proceden de la misma cadena de origen, pero no se puede determinar la cadena original. Si las contrasenas no estan hasheadas y se accede a la base de datos por un tercero no autorizado, todas las cuentas de usuario estan comprometidas. Algunos usuarios pueden (por desgracia) utilizar la misma contrasena para otros servicios. Por lo tanto, es importante tomar en serio la seguridad.