Skip to main content

Objetivo de esta página

Si quieres que un enlace compartido con caducidad use exactamente las condiciones definidas al emitirlo, además de verificar la firma de la URL debes ser coherente con de dónde obtienes los valores. En esta página lo explicamos con un ejemplo que incluye el tipo de informe y el formato de salida en la URL y devuelve un JSON de vista previa. El contenido corresponde a Laravel 13. Para la generación de URLs en general, consulta Generación de URLs, y para los fundamentos de la obtención de entrada, Solicitudes HTTP.
La firma no protege toda la solicitud. Los cuerpos de formularios y JSON no se firman. Obtén los valores de consulta firmados después de verificar la firma, por ejemplo con $request->query('format'). Con input(), all() o las propiedades dinámicas podrías obtener valores del cuerpo que no están firmados. Esta distinción también es necesaria en las solicitudes GET.

Qué protege la firma

input() es una API que maneja no solo la cadena de consulta, sino también el cuerpo. Al combinar estas entradas, Laravel da prioridad a los valores del cuerpo sobre los de la cadena de consulta. En cambio, query() obtiene únicamente la cadena de consulta. Que la verificación de la firma haya tenido éxito y que un valor leído después esté firmado son dos comprobaciones distintas.

Implementar un enlace de vista previa con caducidad

1. Definir la ruta que se verifica

En routes/web.php, define una ruta con nombre que exija firma. Este ejemplo no accede a la base de datos ni a archivos; solo devuelve las condiciones recibidas.
  • El middleware signed verifica la firma y la caducidad antes de ejecutar el closure. Si no son válidas, devuelve 403.
  • Con query() obtienes explícitamente de la cadena de consulta los valores que se usan en el procesamiento.
  • La validación se aplica al array obtenido. La verificación de la firma no garantiza el tipo de los valores ni los rangos permitidos por la lógica de negocio.
En este ejemplo, a Validator::make() solo se le pasan los valores extraídos con query(). Si los sustituyes por $request->all() en un punto cuyo objetivo es validar la consulta firmada, acabarás manejando una entrada que incluye el cuerpo.

2. Generar la URL en un proceso de emisión de confianza

Después de registrar la ruta con nombre, usa el siguiente código en el proceso que emite los enlaces. Como report y format no son marcadores de posición de la ruta, se añaden a la cadena de consulta.
Además de las condiciones indicadas, esta URL contiene expires y signature. expires y signature son parámetros reservados que usa Laravel, así que no los utilices como nombres de tus propios parámetros de negocio. Si expones el proceso de emisión en una aplicación real, no permitas que cualquiera pueda emitir enlaces con condiciones arbitrarias; aplica la autenticación y la autorización necesarias.

3. Comprobar el uso normal

Si abres la URL emitida tal cual dentro del plazo de validez, se devuelve el siguiente JSON.
Si el enlace ha caducado, el middleware signed de la ruta devuelve 403. Las URLs firmadas no son tokens de un solo uso. En este ejemplo, la misma URL puede reutilizarse mientras siga vigente. Si quieres que un enlace solo se use una vez, debes gestionar el estado de uso por separado de la firma.

Separar los valores excluidos de la verificación

Si quieres permitir valores como el número de página que añade el frontend, puedes excluirlos de la verificación de la firma con hasValidSignatureWhileIgnoring(['page']). Sin embargo, cualquiera puede modificar los valores excluidos, así que no los trates como condiciones firmadas. Por ejemplo, page, que sirve para la visualización, cumple una función distinta de report y format, que se fijan al emitir el enlace. No excluyas por simple comodidad los valores que se usan para decidir los datos de destino, los destinatarios, los precios, etc.
El ejemplo anterior usa el middleware signed normal, por lo que tampoco excluye page. Si quieres añadir parámetros de consulta, decide primero qué se firmará tanto en el lado que genera como en el que verifica.

Usar firmas relativas

Si tu diseño no incluye el dominio en la firma, combina absolute: false al generar con signed:relative al verificar.
En este caso, cambia middleware('signed') de la ruta anterior por middleware('signed:relative'). Con las firmas relativas el cuerpo tampoco se firma, así que se mantiene el criterio de obtener los valores con query().

Lista de comprobación para la implementación

  • La ruta receptora exige la verificación de la firma.
  • Los valores de consulta firmados se obtienen con query().
  • El formato y el rango permitido de los valores se validan por separado.
  • Los valores excluidos de la verificación de la firma no se usan como condiciones fijadas al emitir el enlace.
  • La configuración de firma absoluta o relativa coincide en el lado que genera y en el que verifica.
  • Conocer la URL no se considera equivalente a los permisos del usuario autenticado.

Páginas relacionadas y fuentes primarias

Última modificación el 16 de octubre de 2026