Laravel 9+Jetstream登录重定向至Angular SPA时iframe嵌套问题
问题根源
Jetstream搭配Inertia/Vue时,登录请求是通过Inertia的AJAX机制发起的,登录成功后的重定向默认会在Inertia的SPA上下文内处理。如果重定向目标不是Inertia管理的Vue路由(比如你的Angular路由/books/...),Inertia会默认用iframe加载该外部路由内容,同时地址栏停留在登录页(因为是SPA内部的iframe加载,没有触发浏览器级别的导航),这就导致了嵌套iframe的问题。
而直接点击链接或冷加载Angular路由时,是浏览器直接向Laravel发起请求,Laravel路由解析后返回Angular的blade视图,完全绕开了Inertia的SPA上下文,所以一切正常。
彻底解决方案
方案一:修改Laravel端的登录响应逻辑(推荐)
自定义Fortify的登录响应,当重定向目标是Angular路由时,返回普通HTTP重定向而非Inertia的SPA重定向,强制触发浏览器级别的导航:
- 创建自定义登录响应类:
// app/Http/Responses/LoginResponse.php namespace App\Http\Responses; use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract; use Illuminate\Http\RedirectResponse; class LoginResponse implements LoginResponseContract { public function toResponse($request) { $home = config('fortify.home'); // 判断目标路由是否为Angular路由(以/books开头) if (str_starts_with($home, '/books')) { return new RedirectResponse($home); } // 保留原有的Inertia重定向逻辑 return $request->wantsJson() ? response()->json(['two_factor' => false]) : redirect()->intended($home); } }
- 在Fortify服务提供者中替换默认响应:
// app/Providers/FortifyServiceProvider.php use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract; use App\Http\Responses\LoginResponse; public function register() { $this->app->bind(LoginResponseContract::class, LoginResponse::class); }
方案二:在Inertia前端拦截重定向
如果不想修改后端逻辑,可以在Vue的Inertia初始化代码中,拦截重定向请求,当目标是Angular路由时,直接用window.location.href跳转:
// resources/js/app.js import { createInertiaApp } from '@inertiajs/vue3'; createInertiaApp({ resolve: name => require(`./Pages/${name}`), setup({ el, App, props, plugin }) { // 保留原有的setup逻辑 return createApp({ render: () => h(App, props) }) .use(plugin) .mount(el); }, // 添加重定向拦截逻辑 onRedirect(visit) { if (visit.url.startsWith('/books')) { window.location.href = visit.url; return false; // 阻止Inertia的默认重定向行为 } }, });
效果验证
两种方案都能从源头阻止Inertia用iframe加载Angular路由,登录成功后会直接触发浏览器跳转,地址栏更新为目标路由,页面正常加载,不会出现模态框闪烁的问题。
内容的提问来源于stack exchange,提问作者Bytech
相关产品推荐
相关产品推荐

