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

Laravel控制器向后置中间件传参实现旧密码重置令牌失效问询

问题根因

你现有代码存在两个核心错误:

  1. $next($request) 返回的是 Illuminate\Http\Response 对象,不是你控制器返回的数组,所以直接用数组下标读取肯定会失败
  2. 中间件末尾第二次调用 return $next($request) 会重复执行整个请求逻辑,属于严重错误,必须去掉

方案1:解析响应内容(适合需要依赖返回值的场景)

中间件里把响应的JSON内容转成数组读取即可,修改后的中间件代码:

public function handle(Request $request, Closure $next)
{
    // 只调用一次$next,拿到响应对象
    $response = $next($request);
    
    // 解析响应的JSON内容为数组
    $responseData = json_decode($response->getContent(), true);
    
    // 先判断参数存在再操作,避免报错
    if (!isset($responseData['type'], $responseData['email'])) {
        // 不是需要处理的请求,直接返回响应
        return $response;
    }

    $user_email = $responseData['email'];
    $type = $responseData['type'];

    // 批量更新旧令牌,不用查询循环,性能更高
    if ($type == 'reset') {
        Password_reset::where('user_email', $user_email)
            ->where('used', false)
            ->update(['used' => true]);
    } else if ($type == 'confirmation') {
        EmailConfirm::where('user_email', $user_email)
            ->where('used', false)
            ->update(['used' => true]);
    }

    // 直接返回原来的响应,不要再次调用$next
    return $response;
}

方案2:通过Request实例传参(更优雅,不需要解析响应)

Request对象在整个请求生命周期内是共享的,你可以直接在控制器里把参数存到Request里,中间件直接读取:

控制器修改:

在控制器返回前加一行,把需要的参数存到Request中:

// 其他逻辑不变
$reset_token = $reset_request['reset_token'];
$user_email = $request['email'];

// 新增:把参数存到Request实例
$request->attributes->add([
    'operate_type' => 'reset',
    'operate_email' => $user_email
]);

return response(array('message' => 'success', 'email' => $user_email, 'reset_token' => $reset_token, 'type' => 'reset'), status:200);

中间件修改:

public function handle(Request $request, Closure $next)
{
    $response = $next($request);
    
    // 直接从Request里读参数
    $type = $request->attributes->get('operate_type');
    $user_email = $request->attributes->get('operate_email');

    if (!$type || !$user_email) {
        return $response;
    }

    // 批量更新逻辑和方案1一致
    if ($type == 'reset') {
        Password_reset::where('user_email', $user_email)
            ->where('used', false)
            ->update(['used' => true]);
    } else if ($type == 'confirmation') {
        EmailConfirm::where('user_email', $user_email)
            ->where('used', false)
            ->update(['used' => true]);
    }

    return $response;
}

额外优化建议

你原来的循环更新旧令牌的逻辑需要先查询所有记录再逐个保存,IO开销大,直接用update方法做批量更新,一次SQL即可完成操作,性能提升明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:06:08