Laravel多项目单点登录:使用独立SQL Server统一认证
多Laravel项目单点登录(SSO)实现方案
针对你的需求——5个独立部署、各带自有SQL数据库的Laravel项目,通过第6个独立SQL Server完成一次登录即可访问所有项目,同时保留各项目自身数据库运行——以下是基于Laravel生态的落地实现方案:
核心思路
用一个全新的Laravel项目作为SSO认证中心(连接第6个SQL Server),负责统一的用户登录验证与Token发放;5个现有项目通过对接该认证中心验证Token有效性,同时保留自身数据库的业务数据存储与逻辑。这里选用laravel/passport来实现,因为它贴合Laravel生态,能快速完成OAuth2.0协议的落地。
步骤1:搭建SSO认证中心
1.1 初始化认证中心项目
创建新Laravel项目,配置.env连接到你的第6个独立SQL Server。
1.2 配置Laravel Passport
- 安装依赖包:
composer require laravel/passport - 执行数据库迁移(创建Passport所需的Token、客户端表):
php artisan migrate - 生成Passport加密密钥:
php artisan passport:install - 在
User模型中引入Passport的Trait:namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use Laravel\Passport\HasApiTokens; use Illuminate\Notifications\Notifiable; class User extends Authenticatable { use HasApiTokens, Notifiable; protected $fillable = ['name', 'email', 'password']; } - 在
AuthServiceProvider的boot方法中注册Passport路由:namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Laravel\Passport\Passport; class AuthServiceProvider extends ServiceProvider { protected $policies = []; public function boot() { $this->registerPolicies(); Passport::routes(); // 设置Token有效期,按需调整 Passport::tokensExpireIn(now()->addDays(30)); } } - 修改
config/auth.php,将API guard的驱动改为passport:'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ], - 创建一个
/api/user接口,用于返回当前登录用户信息(供其他项目验证Token时调用):Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); });
步骤2:配置5个现有Laravel项目
每个项目都需要对接认证中心,实现Token验证与登录状态同步。
2.1 基础配置
- 安装
laravel/passport(无需执行迁移和passport:install):composer require laravel/passport - 在
config/services.php中添加认证中心的配置:'sso' => [ 'client_id' => env('SSO_CLIENT_ID'), 'client_secret' => env('SSO_CLIENT_SECRET'), 'auth_url' => env('SSO_AUTH_URL'), // 比如https://example.com/sso 'user_info_url' => env('SSO_AUTH_URL').'/api/user', 'token_url' => env('SSO_AUTH_URL').'/oauth/token', ], - 在项目
.env中填入对应值(从认证中心的oauth_clients表获取客户端ID和密钥):SSO_CLIENT_ID=认证中心的客户端ID SSO_CLIENT_SECRET=认证中心的客户端密钥 SSO_AUTH_URL=https://example.com/sso
2.2 实现Token验证中间件
创建一个中间件,用于向认证中心验证请求携带的Token有效性:
namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Http; class VerifySsoToken { public function handle($request, Closure $next) { $token = $request->bearerToken() ?? session('sso_token'); if (!$token) { return redirect()->to(env('SSO_AUTH_URL').'/login?redirect='.urlencode(url()->current())); } // 向认证中心验证Token $response = Http::withToken($token)->get(config('services.sso.user_info_url')); if ($response->failed()) { session()->forget('sso_token'); return redirect()->to(env('SSO_AUTH_URL').'/login?redirect='.urlencode(url()->current())); } // 将认证中心返回的用户信息注入请求 $request->attributes->set('sso_user', $response->json()); // 可选:关联本地用户(如果项目需要本地用户记录) $this->syncLocalUser($response->json()); return $next($request); } private function syncLocalUser(array $ssoUser) { // 首次登录时自动创建本地用户,关联sso用户ID \App\Models\User::firstOrCreate( ['sso_user_id' => $ssoUser['id']], ['name' => $ssoUser['name'], 'email' => $ssoUser['email']] ); } }
在app/Http/Kernel.php中注册该中间件:
protected $routeMiddleware = [ // ... 其他中间件 'sso.auth' => \App\Http\Middleware\VerifySsoToken::class, ];
2.3 处理登录跳转与回调
- 替换原有登录页面的登录按钮,跳转到认证中心:
<a href="{{ env('SSO_AUTH_URL') }}/login?redirect={{ urlencode(url()->current()) }}">统一登录</a> - 在认证中心的登录逻辑中,登录成功后生成Token,跳回原项目的回调路由:
// 认证中心的登录控制器 public function login(Request $request) { // 验证用户 credentials if (Auth::attempt($request->only('email', 'password'))) { $user = Auth::user(); $token = $user->createToken('SSO Token')->accessToken; // 跳回原项目,携带Token return redirect()->to($request->redirect.'?token='.$token); } // 登录失败逻辑 } - 在每个现有项目中添加回调路由,存储Token到Session:
Route::get('/sso/callback', function (Request $request) { session(['sso_token' => $request->token]); return redirect($request->redirect); });
2.4 全局注入Token
创建中间件,自动将Session中的Token注入请求头,避免手动携带:
namespace App\Http\Middleware; use Closure; class InjectSsoToken { public function handle($request, Closure $next) { if (session()->has('sso_token')) { $request->headers->set('Authorization', 'Bearer '.session('sso_token')); } return $next($request); } }
在Kernel.php的web中间件组中添加该中间件:
protected $middlewareGroups = [ 'web' => [ // ... 原有中间件 \App\Http\Middleware\InjectSsoToken::class, ], ];
步骤3:保留项目数据库独立性
所有项目的业务模型(如订单、内容等)依然使用自身的SQL数据库,仅在用户认证环节依赖SSO认证中心。如果需要将业务数据与用户关联,可通过本地用户表的sso_user_id字段关联认证中心的用户ID,如步骤2.2中的syncLocalUser方法所示。
注意事项
- 所有项目必须使用HTTPS协议,避免Token明文传输。
- 可根据需求调整Token有效期,或添加Token自动刷新逻辑。
- 认证中心需做好权限控制,确保只有信任的项目能获取Token。
内容的提问来源于stack exchange,提问作者Yash Bohra
相关产品推荐
相关产品推荐

