Laravel登录在1Password浏览器插件激活时陷入无限循环求助
问题:登录页面因1Password插件陷入无限加载循环
用户反馈登录页面持续无限加载,排查发现1Password浏览器插件会尝试直接登录并跳转Home页面,导致/login与/home反复切换——Home路由受Auth中间件保护,未登录用户访问会被打回/login,最终形成循环。
登录流程采用弹窗式OAuth实现,无传统表单提交,相关前端代码如下:
<script setup> import {ref} from 'vue' import {Head, usePage} from '@inertiajs/vue3' import Auth from '../Layouts/Auth.vue' import ActionButton from '../Components/Buttons/LoungeActionButton.vue' const isLoading = ref(false) const page = usePage() const login = async () => { isLoading.value = true const newWindow = openWindow({ title: 'Login', url: page.props.auth.oauth_url }) if (!newWindow) { alert("The pop-up was blocked by your browser. Please allow popups for this website."); isLoading.value = false; } } window.addEventListener('message', (e) => { if (e.origin !== window.origin) return; location.href = route('test.home'); isLoading.value = false; }, {once: true}); function openWindow({url = '', title = '', width = 600, height = 720} = {}) { const screenWidth = window.innerWidth || document.documentElement.clientWidth || screen.width; const screenHeight = window.innerHeight || document.documentElement.clientHeight || screen.height; const left = (screenWidth - width) / 2 + window.screenLeft ?? window.screen.left; const top = (screenHeight - height) / 2 + window.screenTop ?? window.screen.top; const optionsStr = `width=${width},height=${height},top=${top},left=${left}`; return window.open(url, title, optionsStr); } </script> <template> <Head title="Login"></Head> <Auth> <div class="text-center"> <h1 class="text-3xl font-medium text-[#0053a0] dark:text-[#3493eb]"> {{ $t('app.name') }} </h1> <p class="mb-4 font-light"> {{ $t('For team and network members') }} </p> <ActionButton class="w-80" :disabled="isLoading" @click="login"> {{ $t('Log in with your Member ID') }} </ActionButton> <div class="mt-12"> <a href="https://legacy.iza.org/conference_files/formLogin" class="inline-flex items-center text-sm text-slate-400 dark:text-slate-500 pb-[3px] px-1 border-b border-transparent hover:border-slate-400 dark:hover:border-slate-600 hover:text-[#39c] dark:hover:text-[#3493eb] transition duration-200 ease-in-out" > <font-awesome-icon :icon="['far', 'right-to-bracket']" class="mr-1" aria-hidden="true"/> {{ $t('Login for conference participants') }} </a> </div> </div> </Auth> </template>
曾尝试在RedirectIfAuthenticated中间件中检查OAuth的code查询参数,但登出后仍会陷入循环,中间件代码如下:
public function handle(Request $request, Closure $next, string ...$guards): Response { $guards = empty($guards) ? [null] : $guards; foreach ($guards as $guard) { if (Auth::guard($guard)->check()) { if ($request->query('code')) { return redirect(RouteServiceProvider::HOME); } else { Auth::guard($guard)->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/login'); } } } return $next($request); }
解决方案
1. 修复中间件逻辑
当前中间件会在已登录用户访问/login时直接登出并跳转回/login,这会触发1Password再次尝试自动登录,形成循环。调整逻辑为:已登录用户访问/login时直接跳转Home,仅在主动登出请求时执行登出操作。
修改后的中间件代码:
public function handle(Request $request, Closure $next, string ...$guards): Response { $guards = empty($guards) ? [null] : $guards; foreach ($guards as $guard) { if (Auth::guard($guard)->check()) { // 仅处理主动登出请求 if ($request->routeIs('logout')) { Auth::guard($guard)->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/login'); } // 已登录用户访问登录页直接跳首页 return redirect(RouteServiceProvider::HOME); } } return $next($request); }
2. 限制前端自动跳转条件
当前前端message事件监听会无条件跳转Home,需添加登录成功验证,仅在弹窗返回有效登录标识时跳转:
window.addEventListener('message', (e) => { if (e.origin !== window.origin) return; // 验证弹窗返回的登录成功标识 if (e.data?.success) { location.href = route('test.home'); isLoading.value = false; } }, {once: true});
同时确保OAuth授权完成后,弹窗向主窗口发送的消息包含success: true标识。
3. 兼容1Password自动检测逻辑
1Password会自动识别登录表单并触发自动操作,可添加隐藏的禁用表单避免插件误判:
<!-- 在登录页面的template中添加 --> <form style="display: none"> <input type="email" disabled> <input type="password" disabled> <button type="submit" disabled></button> </form>
是否为1Password的Bug?
这并非纯粹的插件Bug,而是1Password自动登录逻辑与无表单登录流程的兼容性问题。插件默认会检测页面中的登录表单并尝试自动填充提交,你的弹窗式登录无传统表单,插件误触发了跳转行为,加上中间件逻辑的缺陷,最终导致循环。
内容的提问来源于stack exchange,提问作者Elbern
相关产品推荐
相关产品推荐

