jpm/session-sharing-bundle

允许已知服务器之间使用同步加密进行会话共享

安装: 11

依赖项: 0

建议者: 0

安全: 0

星星: 1

关注者: 2

分支: 0

开放问题: 0

类型:symfony-bundle

1.0.1 2023-07-20 10:35 UTC

This package is auto-updated.

Last update: 2024-09-20 13:14:41 UTC


README

这是一个 Symphony 会话共享包,允许远程服务器从主机(IDP)请求并接收 sessionId。数据通过 HTTP 协议传输,该协议通过同步加密进行保护。一旦通过 REDIS 服务共享会话,远程系统可以检索 AuthUser 信息。

使用以下命令安装包:

composer require jpm/session-sharing-bundle

用法

PoC 演示

在下一节中,您将找到如何安装和使用的步骤,但如果您更喜欢,可以观看包含包用法演示的视频

主机端设置

  1. 安装 composer require jpm/session-sharing-bundle
  2. 然后运行 php bin/console jpm:generate-sync-key 生成一个随机密钥。
    • 此密钥是敏感信息,您必须保密。
    • 输出密钥通常以 def... 开头。
  3. 在您的 .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 ###
  4. 现在要创建订阅者,使用命令: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'
        ];
     }
     }

远程端设置

  1. 也要安装 composer require jpm/session-sharing-bundle
  2. 现在在您的 .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 ###
  3. 现在需要创建订阅者,使用命令: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 项目之间共享会话的问题,同时保持最低的安全级别,即使在不同的域名下托管。

用例示例

  1. 未知用户访问 http://remote.test
  2. 请求被 SessionManagerSubscriber 截获,用户通过回调信息(HTTP 302)被重定向到身份提供者。
  3. IDP(主机)接收一个 GET 请求:http://host-idp.test/login?callback=aHR0cDovL3JlbW90ZS50ZXN0
  4. IDP(主机)的 RemoteAuthSubscriber 截获调用,解密回调参数,提取域名,并确认它是否属于允许的域名列表(JPM_KNOWN_REMOTE_HOSTS)。
    • 如果不是:执行授权/查询但不转发给未知请求者。
  5. 一旦请求被验证,IDP 检查用户是否有一个有效的会话打开。
    • 如果没有,IDP 身份验证表单显示给用户,并保留回调参数。
  6. 一旦会话创建(或存在),"SessionID" 使用同步密钥和 defuse lib 加密。
  7. 现在用户被重定向回回调URL,其中包含包含加密值的令牌参数。
  8. 远程应用程序接收到的请求为:http://remote.test?token=ZGVmNTAyMDAwYjliZDI5ODU5NGQxYzQwYTE...
  9. 再次,SessionManagerSubscriber 拦截请求,但一旦找到令牌,它会对其进行解码和解密,恢复会话,并最终让识别出的用户访问资源

责任声明

安全性非常重要,不同系统之间共享数据库/redis绝不可取,在GET请求之间发送敏感数据非常糟糕,但不幸的是,有时我们需要为这些情况创建某种解决方案。

会话共享的自然解决方案是使用JWT或其他基于令牌的解决方案。我这样做是为了作为一个研究实验室,这可能会为我们提供一些关于不同事物的见解,所以我建议在生产环境中使用此方法,除非你理解在不同系统之间共享敏感数据和HTTP通信的风险。