
本文介绍如何利用 laravel sanctum 在物理隔离、不同代码仓库的两个 laravel 应用(app a 与 app b)之间安全共享用户会话与认证状态,支持跨域 token 验证与无状态登录。
本文介绍如何利用 laravel sanctum 在物理隔离、不同代码仓库的两个 laravel 应用(app a 与 app b)之间安全共享用户会话与认证状态,支持跨域 token 验证与无状态登录。
Laravel Sanctum 原生设计支持两种主要认证模式:Token-based API 认证(适用于 SPA 或移动客户端)和 Cookie-based Web 认证(适用于传统服务端渲染应用)。当两个 Laravel 应用需共享同一套用户体系并实现“一次登录、多端通行”时,推荐采用 Cookie + CSRF + Sanctum API Token 的混合方案,前提是它们共享同一根域名(如 app-a.example.com 和 app-b.example.com)或可配置为信任的同源/跨域环境。
✅ 前提条件
- 两个应用均使用 Laravel ≥ 8.0 + Sanctum ≥ 2.0;
- 共享同一数据库(用户表共用),或通过 UserProvider 自定义同步逻辑(如 JWT 中继、OAuth2 中心化授权);
- App A 作为认证中心(Auth Server),App B 作为受信客户端(Resource Client);
- 若跨子域,需统一配置 SESSION_DOMAIN=.example.com 和 SANCTUM_STATEFUL_DOMAINS=app-a.example.com,app-b.example.com。
? 关键配置步骤(以 App A 为认证源)
-
在 App A 中启用 Sanctum 并暴露登录接口
// routes/api.php (App A) use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; Route::post('/login', function (Request $request) { $credentials = $request->validate([ 'email' => ['required', 'email'], 'password' => ['required'], ]); if (Auth::attempt($credentials)) { $user = Auth::user(); $token = $user->createToken('app-b-access')->plainTextToken; return response()->json(['token' => $token]); } return response()->json(['message' => 'Unauthorized'], 401); }); -
App B 配置 Sanctum 为 API 消费者
在 .env 中指定 App A 的 API 地址,并禁用本地 Session 登录(改用 Token 认证):# .env (App B) SANCTUM_STATEFUL_DOMAINS=app-b.example.com APP_A_API_URL=https://app-a.example.com
在 config/sanctum.php 中确保 stateful 匹配前端域名:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1,app-b.example.com')), -
App B 登录逻辑(调用 App A 接口)
// LoginController@authenticate (App B) public function authenticate(Request $request) { $response = Http::asForm()->post(config('app.app_a_api_url').'/api/login', [ 'email' => $request->email, 'password' => $request->password, ]); if ($response->successful()) { $token = $response->json()['token']; // 将 token 存入本地 session 或 localStorage(SPA 场景) session(['sanctum_token' => $token]); return redirect()->intended('/dashboard'); } return back()->withErrors(['email' => 'Invalid credentials']); } -
API 请求携带 Token(App B 调用自身受保护接口时)
// App B 中受保护路由示例 Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user(); // 自动解析 token 并加载用户 });
⚠️ 注意事项
- ❌ 不要直接共享 SESSION_DRIVER=database 或 redis 实例来“复用 Session”——这违背无状态设计且存在安全与扩展风险;
- ✅ 推荐将 App A 作为唯一认证入口,App B 仅负责 Token 校验(Sanctum 默认支持 Bearer Token 解析);
- ? 生产环境务必启用 HTTPS,禁用 APP_DEBUG=true,并对 /api/login 加速率限制(throttle:api);
- ? 若两应用完全跨域(如 a.com ↔ b.net),则必须使用 Sanctum 的 Token 认证模式(非 Cookie 模式),并通过 Authorization: Bearer {token} 头传递,此时 stateful 配置无效,需手动在中间件中校验。
✅ 总结
通过 Sanctum 的灵活 Token 机制,两个独立 Laravel 应用可安全、解耦地实现统一认证体验。核心在于:App A 提供标准化登录接口并签发 Token;App B 消费该 Token 并交由 Sanctum 中间件统一验证。无需引入 OAuth2 服务器等重型组件,即可达成轻量、可控、符合 Laravel 生态的最佳实践。










