基于Symfony的两个跨子域名应用实现单点登录方案咨询
适配多子域名Symfony应用的SSO方案选择与JWT实现指南
方案选型建议
你的场景是同主域下不同子域名的Symfony应用,基于JWT的SSO是最适配的方案,理由如下:
- 无需额外搭建独立认证中心,两个应用直接通过JWT互信,落地成本低
- 子域名场景下可通过Cookie传递JWT(配置Cookie的Domain属性为主域名,比如
.example.com),安全且用户无感知 - Symfony生态有成熟的JWT组件支持,适配性强
如果后续需要扩展更多应用,也可以升级为独立认证中心模式,但当前场景下JWT直接互信完全够用。
Symfony下JWT实现SSO的步骤
1. 统一JWT配置(两个应用共享)
在两个Symfony应用中安装lexik/jwt-authentication-bundle:
composer require lexik/jwt-authentication-bundle
生成一次密钥对,复制到两个应用的config/jwt/目录下:
openssl genrsa -out config/jwt/private.pem -aes256 4096 openssl rsa -pubout -in config/jwt/private.pem -out config/jwt/public.pem
确保两个应用的config/packages/lexik_jwt_authentication.yaml配置一致,重点设置:
lexik_jwt_authentication: secret_key: '%env(resolve:JWT_SECRET_KEY)%' public_key: '%env(resolve:JWT_PUBLIC_KEY)%' pass_phrase: '%env(JWT_PASSPHRASE)%' token_ttl: 3600 # 按需调整过期时间 cookie: enabled: true name: APP_JWT domain: '.example.com' # 主域名,确保子域名可读取 secure: true # 生产环境开启HTTPS时设为true http_only: true same_site: lax
2. WebApp_A配置:登录后发放JWT并写入Cookie
在WebApp_A的登录逻辑中,登录成功后生成JWT并通过Cookie返回。如果使用Symfony Security表单登录,可在SecurityController的登录方法中添加:
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Response; // ... public function login(AuthenticationUtils $authenticationUtils, JWTTokenManagerInterface $jwtManager, Request $request): Response { // 原有登录逻辑... if ($this->getUser()) { $token = $jwtManager->create($this->getUser()); $cookie = Cookie::create('APP_JWT') ->setValue($token) ->setDomain('.example.com') ->setHttpOnly(true) ->setSecure($request->isSecure()) ->setSameSite('lax') ->setMaxAge(3600); return $this->redirectToRoute('home', [], Response::HTTP_OK)->headers->setCookie($cookie); } // ... }
3. WebApp_B配置:验证JWT Cookie实现自动登录
在WebApp_B的config/packages/security.yaml中,添加JWT防火墙配置:
security: firewalls: main: lazy: true jwt: provider: app_user_provider # 需与WebApp_A共享用户数据源(如同一数据库) form_login: login_path: app_login check_path: app_login logout: path: app_logout
确保WebApp_B的用户提供者能从共享数据源获取用户信息,验证JWT中的用户标识(如username或email)后即可自动登录。
4. 测试SSO流程
- 在WebApp_A登录,检查浏览器Cookie中是否存在
APP_JWT,域名显示为.example.com - 点击WebApp_A中指向WebApp_B受保护路由的链接,WebApp_B会自动读取Cookie中的JWT,验证通过后直接登录,无需重复输入账号密码
注意事项
- 两个应用必须共享用户数据(如同一数据库),否则WebApp_B无法识别JWT中的用户
- 生产环境必须开启HTTPS,防止JWT被窃取
- 定期更换JWT密钥,避免密钥泄露引发安全问题
- 如需注销SSO,需在两个应用中同时清除JWTCookie,或添加JWT黑名单机制
内容的提问来源于stack exchange,提问作者marcusm
相关产品推荐
相关产品推荐

