本页目的
在限时分享链接中,如果希望直接使用签发时确定的条件,除了验证 URL 签名之外,还需要统一从哪里获取值。 本页以一个示例进行说明:在 URL 中包含报表类型和输出格式,并返回用于预览的 JSON。 本页适用于 Laravel 13。URL 生成的整体介绍请参阅 URL 生成,获取输入的基础知识请参阅 HTTP 请求。签名保护的范围
input() 不仅处理查询字符串,也处理请求体。Laravel 在合并这些输入时,请求体中的值优先于查询字符串中的值。
而 query() 只获取查询字符串中的值。
签名验证成功,与之后读取的值是否已签名,是两件需要分别确认的事情。
实现限时预览链接
1. 定义进行验证的路由
在routes/web.php 中定义一个必须带签名的命名路由。
这里不操作数据库或文件,只返回接收到的条件。
signed中间件会在闭包执行前验证签名和有效期。若无效,则返回403。- 使用
query()从查询字符串中显式获取处理所需的值。 - 校验针对获取到的数组进行。签名验证并不保证值的类型或业务上允许的范围。
本示例中传给
Validator::make() 的只有通过 query() 取出的值。
如果在用于校验已签名查询值的地方改用 $request->all(),就会处理到包含请求体在内的输入。2. 在可信的签发流程中生成 URL
注册命名路由后,在签发链接的处理中使用以下代码。report 和 format 不是路径占位符,因此会被添加到查询字符串中。
expires 和 signature。
expires 和 signature 是 Laravel 使用的保留参数,请不要将它们用作业务参数名。
在实际应用中公开签发流程时,不要让任何人都能以任意条件签发链接,并进行必要的认证和授权。
3. 确认正常使用
在有效期内直接打开签发的 URL,会返回以下 JSON。signed 中间件会返回 403。
签名 URL 并不是一次性令牌。在本示例中,有效期内可以重复使用同一个 URL。
如果只允许使用一次,需要在签名之外另行管理已使用状态。
区分从验证中排除的值
如果希望允许前端追加的页码等参数,可以通过hasValidSignatureWhileIgnoring(['page']) 将其从签名验证中排除。
但被排除的值任何人都可以修改,因此不要将其视为已签名的条件。
例如,用于显示的 page 与签发时固定的 report、format 作用不同。
不要仅仅为了方便,就排除那些用于判断目标数据、接收者、费用等的值。
使用相对签名时
在签名中不包含域名的设计中,需要组合使用生成时的absolute: false 和验证时的 signed:relative。
middleware('signed') 改为 middleware('signed:relative')。
即使使用相对签名,请求体也不会被签名,因此通过 query() 获取值的方针不变。
实现检查清单
- 接收路由强制要求签名验证。
- 通过
query()获取已签名的查询值。 - 另行校验值的格式和允许范围。
- 没有将从签名验证中排除的值当作签发时固定的条件使用。
- 生成端与验证端的绝对签名、相对签名设置保持一致。
- 没有将知道 URL 等同于已登录用户的权限。
相关页面与一手资料
- URL 生成:签名 URL 的 API 以及对无效签名的响应
- HTTP 请求:获取输入值和查询字符串
- 校验:校验输入格式和允许的值
- Laravel 官方文档:Signed URLs
- Laravel 官方文档:Retrieving input from the query string
- Laravel Framework:UrlGenerator
- Laravel Framework:ValidateSignature