Laravel 9.x redirect()->intended未跳转至预期URL反而返回原路由问题
Laravel 9密码确认后无法跳转至POST路由的解决方案
问题根源
Laravel 默认的 password.confirm 中间件在拦截非GET请求时,仅会将目标URL存入session的url.intended字段,但丢失了请求方法(如POST)和提交的表单数据。因此密码确认完成后,redirect()->intended()只能跳转到对应的GET路由,无法还原原本的POST请求逻辑。
解决步骤
1. 自定义密码确认中间件
创建一个继承自默认中间件的自定义中间件,用于存储请求方法和表单数据:
<?php namespace App\Http\Middleware; use Illuminate\Auth\Middleware\EnsurePasswordIsConfirmed as BaseMiddleware; class EnsurePasswordIsConfirmedWithMethod extends BaseMiddleware { protected function storeIntendedUrl($request) { // 存储完整目标URL、请求方法及表单数据 $request->session()->put([ 'url.intended' => $request->fullUrl(), 'request.method' => $request->method(), 'request.input' => $request->all(), ]); } }
2. 替换默认中间件别名
在app/Http/Kernel.php中,将默认的password.confirm中间件替换为自定义的:
protected $routeMiddleware = [ // 其他中间件... 'password.confirm' => \App\Http\Middleware\EnsurePasswordIsConfirmedWithMethod::class, ];
3. 修改密码确认路由的处理逻辑
更新POST类型的/confirm-password路由,根据session存储的信息还原原请求:
use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; Route::post('/confirm-password', function (Request $request) { if (!Hash::check($request->password, $request->user()->password)) { return back()->withErrors([ 'password' => ['提供的密码与记录不符。'] ]); } $request->session()->passwordConfirmed(); // 从session取出存储的请求信息 $intendedUrl = $request->session()->pull('url.intended', '/'); $method = $request->session()->pull('request.method', 'GET'); $input = $request->session()->pull('request.input', []); // GET请求直接跳转 if ($method === 'GET') { return redirect()->to($intendedUrl); } // 非GET请求生成自动提交的表单,还原请求方法和数据 return response()->view('auth.password.redirect-form', [ 'url' => $intendedUrl, 'method' => $method, 'input' => $input, ]); })->middleware(['auth', 'throttle:6,1']);
4. 创建自动跳转表单视图
在resources/views/auth/password/目录下新建redirect-form.blade.php,用于自动提交表单还原原请求:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>正在跳转...</title> <script> document.addEventListener('DOMContentLoaded', () => { document.getElementById('redirect-form').submit(); }); </script> </head> <body> <form id="redirect-form" action="{{ $url }}" method="{{ strtolower($method) }}"> @foreach($input as $key => $value) @if(is_array($value)) @foreach($value as $subKey => $subValue) <input type="hidden" name="{{ $key }}[{{ $subKey }}]" value="{{ $subValue }}"> @endforeach @else <input type="hidden" name="{{ $key }}" value="{{ $value }}"> @endif @endforeach <p>如果未自动跳转,请点击下方按钮:</p> <button type="submit">继续</button> </form> </body> </html>
原理说明
通过自定义中间件扩展了原有的意图存储逻辑,不仅保存目标URL,还记录了请求方法和表单数据。密码确认完成后,针对非GET请求,通过生成自动提交的表单来还原原本的请求,从而实现跳转到POST路由并执行对应的保存逻辑。
内容的提问来源于stack exchange,提问作者Ashaurance Heavens
相关产品推荐
相关产品推荐

