jpm / session-sharing-bundle
允许已知服务器之间使用同步加密进行会话共享
1.0.1
2023-07-20 10:35 UTC
Requires
- php: >=8.1
- defuse/php-encryption: ^2.4
- symfony/console: ^6.3
- symfony/dependency-injection: ^6.3
- symfony/dotenv: ^6.3
- symfony/http-kernel: ^6.3
- symfony/security-bundle: ^6.3
- symfony/serializer-pack: ^1.3
- symfony/yaml: ^6.3
Requires (Dev)
- symfony/test-pack: ^1.1
README
这是一个 Symphony 会话共享包,允许远程服务器从主机(IDP)请求并接收 sessionId。数据通过 HTTP 协议传输,该协议通过同步加密进行保护。一旦通过 REDIS 服务共享会话,远程系统可以检索 AuthUser 信息。
使用以下命令安装包:
composer require jpm/session-sharing-bundle
用法
PoC 演示
在下一节中,您将找到如何安装和使用的步骤,但如果您更喜欢,可以观看包含包用法演示的视频。
主机端设置
- 安装
composer require jpm/session-sharing-bundle
。 - 然后运行
php bin/console jpm:generate-sync-key
生成一个随机密钥。- 此密钥是敏感信息,您必须保密。
- 输出密钥通常以
def...
开头。
- 在您的
.env
文件中,添加以下键JPM_TOKEN_SYNC_SECRET
使用您生成的密钥。JPM_APP_URL
使用您的地址。JPM_KNOWN_REMOTE_HOSTS
已知主机域名,每个条目之间用逗号分隔。以下是一个示例###> jpm/session-sharing keys ### JPM_TOKEN_SYNC_SECRET=def0000031429fb75a...69057f875ff4c6118cb8c1 JPM_APP_URL=http://host-idp.test JPM_KNOWN_REMOTE_HOSTS=remote.test ###< jpm/session-sharing keys ###
- 现在要创建订阅者,使用命令:
php bin/console make:subscriber RemoteAuth
或在./src/EventSubscriber/RemoteAuthSubscriber.php
中手动创建类。use JPM\SessionSharingBundle\Service\JpmSessionClient; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; class RemoteAuthSubscriber implements EventSubscriberInterface { public function __construct( private JpmSessionClient $remoteAppHelper ){} public function onKernelResponse( ResponseEvent $event ): void { $this->remoteAppHelper->watchRemoteSessionRequest($event); } public static function getSubscribedEvents(): array { return [ KernelEvents::RESPONSE => 'onKernelResponse' ]; } }
远程端设置
- 也要安装
composer require jpm/session-sharing-bundle
。 - 现在在您的
.env
文件中添加以下键JPM_TOKEN_SYNC_SECRET
使用与主机相同的密钥。JPM_APP_URL
使用您的真实域名。JPM_IDP_URL
使用执行登录操作的宿主路由。以下是一个示例###> jpm/session-sharing keys ### JPM_TOKEN_SYNC_SECRET=def0000031429fb75a...69057f875ff4c6118cb8c1 JPM_APP_URL=http://remote.test JPM_IDP_URL=http://host-idp.test/login ###< jpm/session-sharing keys ###
- 现在需要创建订阅者,使用命令:
php bin/console make:subscriber SessionManager
或在./src/EventSubscriber/SessionManagerSubscriber.php
中手动创建类。use JPM\SessionSharingBundle\Service\JpmSessionClient; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ControllerEvent; use Symfony\Component\HttpKernel\KernelEvents; class SessionManagerSubscriber implements EventSubscriberInterface { public function __construct( private JpmSessionClient $remoteAppHelper, ){} public function onKernelController(ControllerEvent $event): void { $this->remoteAppHelper->watchSessionRefresh($event); } public static function getSubscribedEvents(): array { return [ KernelEvents::CONTROLLER => 'onKernelController', ]; } }
基本上,这允许您的远程项目通过请求从主机获取 SessionId,并由 REDIS/数据库无问题地检索。
架构生命周期
此包使用 Symfony 组件解决在不同 Symfony 项目之间共享会话的问题,同时保持最低的安全级别,即使在不同的域名下托管。
用例示例
- 未知用户访问
http://remote.test
。 - 请求被
SessionManagerSubscriber
截获,用户通过回调信息(HTTP 302)被重定向到身份提供者。 - IDP(主机)接收一个 GET 请求:
http://host-idp.test/login?callback=aHR0cDovL3JlbW90ZS50ZXN0
。 - IDP(主机)的
RemoteAuthSubscriber
截获调用,解密回调参数,提取域名,并确认它是否属于允许的域名列表(JPM_KNOWN_REMOTE_HOSTS
)。- 如果不是:执行授权/查询但不转发给未知请求者。
- 一旦请求被验证,IDP 检查用户是否有一个有效的会话打开。
- 如果没有,IDP 身份验证表单显示给用户,并保留回调参数。
- 一旦会话创建(或存在),"SessionID" 使用同步密钥和 defuse lib 加密。
- 现在用户被重定向回回调URL,其中包含包含加密值的令牌参数。
- 远程应用程序接收到的请求为:
http://remote.test?token=ZGVmNTAyMDAwYjliZDI5ODU5NGQxYzQwYTE...
- 再次,
SessionManagerSubscriber
拦截请求,但一旦找到令牌,它会对其进行解码和解密,恢复会话,并最终让识别出的用户访问资源
责任声明
安全性非常重要,不同系统之间共享数据库/redis绝不可取,在GET请求之间发送敏感数据非常糟糕,但不幸的是,有时我们需要为这些情况创建某种解决方案。
会话共享的自然解决方案是使用JWT或其他基于令牌的解决方案。我这样做是为了作为一个研究实验室,这可能会为我们提供一些关于不同事物的见解,所以我不建议在生产环境中使用此方法,除非你理解在不同系统之间共享敏感数据和HTTP通信的风险。