Laravel实现跨子域及多域名统一认证单点登录方案咨询
Laravel 跨子域及多独立域名统一身份认证实现方案
一、同根域名跨子域认证适配(*.mysite.com 场景)
你的现有路由配置不需要做太大调整,只需要统一 Session 配置即可实现同根域名下所有子域登录态共享:
- 修改
config/session.php配置项:'domain' => env('SESSION_DOMAIN', '.mysite.com'),注意域名前加.,表示所有一级子域都可读取 Session Cookie'same_site' => 'lax',平衡安全性和跨域可用性- 统一所有子域的 Session 驱动,推荐使用
redis或database,确保所有子域读取同一份 Session 数据
- 同步修改
.env文件中的SESSION_DOMAIN=.mysite.com即可完成子域适配,此时用户在 auth.mysite.com 登录后,直接访问 my.mysite.com 即可识别登录态。
二、多独立域名单点登录实现(mysite2.com、notmysite.com 等非同源场景)
独立域名之间浏览器无法共享 Cookie,需要基于统一认证中心的模式实现单点登录,你现有的 auth.mysite.com 可直接作为认证中心,实现逻辑如下:
核心流程
- 用户访问独立域名下的受保护资源时,如果未登录,自动跳转至
https://auth.mysite.com/login?redirect={当前页面地址} - 用户在 auth.mysite.com 完成登录后,生成一个有效期5分钟、单次有效的临时授权 Ticket,携带 Ticket 跳转回原独立域名的回调地址
- 独立域名后端收到 Ticket 后,内部请求 auth.mysite.com 的 Ticket 校验接口,校验通过后在当前独立域名下写入登录态,完成单点登录
代码示例
1. 所有业务域名新增 SSO 回调路由
// 放在所有业务域名的路由组内 Route::get('/sso/callback', function (\Illuminate\Http\Request $request) { $ticket = $request->query('ticket'); if (empty($ticket)) abort(400, '缺少授权凭证'); // 后端内部请求认证中心校验 Ticket,不走浏览器跨域 $verifyResult = \Illuminate\Support\Facades\Http::post('https://auth.mysite.com/api/sso/verify', [ 'ticket' => $ticket, 'domain' => $request->getHost() ]); if (!$verifyResult->successful() || !$verifyResult->json('valid')) { abort(403, '授权验证失败'); } // 校验通过后给当前域名写入登录态 \Auth::loginUsingId($verifyResult->json('user_id')); // 跳转至用户最初访问的页面 return redirect()->intended('/'); });
2. 认证中心(auth.mysite.com)新增 Ticket 生成与校验逻辑
// 登录逻辑完成后生成 Ticket 跳转 public function login(\Illuminate\Http\Request $request) { // 原有登录校验逻辑... if (\Auth::attempt($credentials)) { if ($redirect = $request->query('redirect')) { $domain = parse_url($redirect, PHP_URL_HOST); // 先校验域名是否在允许的白名单内,防止恶意跳转 if (!in_array($domain, config('sso.allow_domains'))) { return redirect('/dashboard'); } // 生成单次有效Ticket,存储5分钟 $ticket = Str::random(32); \Cache::put('sso_ticket:'.$ticket, [ 'user_id' => \Auth::id(), 'domain' => $domain ], 300); return redirect($redirect . '/sso/callback?ticket=' . $ticket); } return redirect('/dashboard'); } // 登录失败逻辑... } // 新增Ticket校验接口 Route::post('/api/sso/verify', function (\Illuminate\Http\Request $request) { $ticketKey = 'sso_ticket:' . $request->input('ticket'); $ticketInfo = \Cache::get($ticketKey); if (!$ticketInfo || $ticketInfo['domain'] !== $request->input('domain')) { return response()->json(['valid' => false], 400); } // 校验完成后立即删除Ticket,保证单次有效 \Cache::forget($ticketKey); return response()->json(['valid' => true, 'user_id' => $ticketInfo['user_id']]); });
注意事项
- 提前在认证中心配置允许接入的域名白名单,防止恶意域名窃取授权
- Ticket 必须设置短有效期且单次有效,避免泄露后被冒用
- 统一登出场景可在认证中心触发登出时,通知所有绑定域名清除各自的登录态Cookie
内容的提问来源于stack exchange,提问作者Zikrulloh Tolibjonov
相关产品推荐
相关产品推荐

