You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Laravel临时签名路由提交/打开一次后立即过期?

实现Laravel临时签名路由一次性失效

要让生成的临时签名路由在首次访问/提交后立即失效,需要在Laravel自带的签名验证基础上,额外添加已使用标记的校验。以下是两种可行的实现方案:

方案一:使用缓存实现(轻量快捷)

这种方式无需新增数据库表,适合快速实现:

1. 生成带唯一Token的签名路由

生成路由时,额外添加一个唯一随机Token作为参数,确保每个路由实例唯一:

use Illuminate\Support\Str;
use Illuminate\Support\Facades\URL;

$token = Str::random(32);
$myRoute = URL::temporarySignedRoute(
    'unsubscribe', 
    now()->addMinutes(30), 
    ['user' => 1, 'token' => $token]
);

2. 在路由处理逻辑中校验并标记已使用

在unsubscribe路由对应的控制器方法里,先验证签名有效性,再检查缓存是否存在该Token:

use Illuminate\Support\Facades\Cache;

public function unsubscribe(Request $request)
{
    // 验证签名有效性(Laravel会自动处理,也可手动调用)
    if (!$request->hasValidSignature()) {
        abort(403, '无效的链接');
    }

    $token = $request->input('token');
    $cacheKey = "used_signed_route:{$token}";

    // 检查该链接是否已被使用
    if (Cache::has($cacheKey)) {
        abort(403, '该链接已失效');
    }

    // 标记链接为已使用,缓存有效期和路由一致(30分钟)
    Cache::put($cacheKey, true, now()->addMinutes(30));

    // 执行 unsubscribe 业务逻辑
    // ...

    return response('退订成功');
}

方案二:使用数据库记录(持久化,适合需要审计的场景)

如果需要长期记录链接的使用情况,可以用数据库表存储:

1. 创建迁移文件生成记录表

php artisan make:migration create_signed_route_usages_table

编辑迁移文件,添加必要字段:

public function up()
{
    Schema::create('signed_route_usages', function (Blueprint $table) {
        $table->id();
        $table->unsignedInteger('user_id')->nullable(); // 关联用户(可选)
        $table->string('route_name'); // 路由名称
        $table->string('token')->unique(); // 唯一Token
        $table->timestamp('used_at')->nullable(); // 使用时间
        $table->timestamps();
    });
}

public function down()
{
    Schema::dropIfExists('signed_route_usages');
}

执行迁移:

php artisan migrate

2. 生成带Token的签名路由

和缓存方案一样,生成路由时添加唯一Token,并提前存入数据库标记为未使用:

use Illuminate\Support\Str;
use Illuminate\Support\Facades\URL;
use App\Models\SignedRouteUsage;

$token = Str::random(32);
$myRoute = URL::temporarySignedRoute(
    'unsubscribe', 
    now()->addMinutes(30), 
    ['user' => 1, 'token' => $token]
);

SignedRouteUsage::create([
    'user_id' => 1,
    'route_name' => 'unsubscribe',
    'token' => $token,
]);

3. 控制器中校验并标记已使用

use App\Models\SignedRouteUsage;

public function unsubscribe(Request $request)
{
    if (!$request->hasValidSignature()) {
        abort(403, '无效的链接');
    }

    $token = $request->input('token');
    $routeUsage = SignedRouteUsage::where('token', $token)->first();

    if (!$routeUsage || $routeUsage->used_at) {
        abort(403, '该链接已失效');
    }

    // 标记为已使用
    $routeUsage->update(['used_at' => now()]);

    // 执行退订逻辑
    // ...

    return response('退订成功');
}

注意事项

  • 无论哪种方案,都要确保token参数的唯一性,避免不同用户的路由出现冲突。
  • 缓存方案的优势是无需维护数据库,性能更高;数据库方案适合需要追溯链接使用记录的场景。

内容的提问来源于stack exchange,提问作者Gabriel Rogath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 09:52:35