Laravel 跳转到子域名时如何实现自动登录无需重复认证
你的现有方案存在的致命问题
- 逻辑错误:
Auth::user()->password取到的是哈希加密后的密码,而Auth::attempt()方法要求传入明文密码才能和库中的哈希值匹配验证,所以你传加密后的密码永远不可能验证通过。 - 跨域参数传递失效:Laravel 的
Redirect::with()是将参数存到当前域名的 session 闪存中,跨子域名默认 session 不互通,目标站点根本拿不到你传递的 email 和 password 参数。 - 安全风险:直接传递用户密码(哪怕是哈希值)属于严重的敏感信息泄露风险,完全不符合安全规范。
可落地的实现方案
场景1:两个子域名属于同一个一级域名(改造成本最低,优先用这个方案)
直接配置跨子域名 session 共享即可,不需要额外写跳转逻辑:
- 打开项目
config/session.php文件,将domain配置项改为.你的一级域名.com,比如两个子域名是a.xxx.com和b.xxx.com,就填.xxx.com(注意前面带点)。 - 确保两个子域名对应的项目配置中,
APP_KEY、session 驱动、cookie 名称、加密规则完全一致。
配置完成后,用户在任意一个子域名登录后,访问另一个子域名会自动识别登录状态,不需要额外跳转验证。
场景2:两个子域名不属于同一个一级域名
用一次性签名令牌方案实现安全免登跳转,全程不传递敏感信息:
- 修改切换数据库的Controller逻辑
function change_database(Request $request){ $targetDomain = $request->selected_database; // 生成唯一一次性令牌,绑定用户ID和当前时间戳 $token = hash('sha256', Auth::id() . now()->timestamp . config('app.key')); // 令牌存入公共缓存(比如共用的Redis),有效期5分钟,关联对应用户ID Cache::put('cross_domain_login_'.$token, Auth::id(), 300); // 携带令牌跳转到目标域名的专用验证接口 return Redirect::to($targetDomain . '/cross-domain-login?token=' . $token); }
- 在两个项目的web.php中新增跨域验证路由
Route::get('/cross-domain-login', function (Request $request) { // 校验令牌有效性 if (!$request->has('token') || !Cache::has('cross_domain_login_'.$request->token)) { return redirect('/')->withErrors('跳转链接无效,请重新登录'); } $userId = Cache::get('cross_domain_login_'.$request->token); // 令牌用完立即销毁,防止被盗用重复使用 Cache::delete('cross_domain_login_'.$request->token); // 校验目标库是否存在该用户,存在直接登录 if(User::where('id', $userId)->exists()){ Auth::loginUsingId($userId); return redirect('/dashboard'); } return redirect('/')->withErrors('您没有该站点的访问权限'); }); // 原有的首页路由不需要改 Route::get('/', function () { return view('auth.login'); });
注意事项
- 如果两个项目的缓存是独立部署的,需要共用同一个缓存服务(比如Redis),确保两边都能读取到跨域登录的令牌。
- 令牌必须设置短有效期,且用完立即销毁,避免被截获后盗用。
内容的提问来源于stack exchange,提问作者Hege
相关产品推荐
相关产品推荐

