无法读取旧会话

问题描述 投票:0回答:2

我有一个旧版 API 应用程序,它可以生成传统的

session_start();
并将数据填充到
$_SESSION
中。
现在我正在用Symfony 6.4做一个v2 API,在相同的环境中,我想读取数据形式
$_SESSION

我发现与遗留应用程序集成
我不知道遗留应用程序是否有提到的

own PHP save handler
,我只是尝试了所有可能的配置组合。

framework:
    session:
        storage_factory_id: session.storage.factory.php_bridge

我取下了

var/cache
并加热了它。

结果:

  • $_SESSION
    :未定义
  • $this->requestStack->getSession()
    :给出一个复杂的对象树,没有遗留会话数据,但带有空数组的奇怪 Symfony 键
    _sf2_attributes
    _symfony_flashes
  • $this->requestStack->getSession()->get('keyInLegacySession')
    :空
framework:
    session:
        storage_factory_id: session.storage.factory.php_bridge
        handler_id: ~

我取下了

var/cache
并加热了它。

结果:同上。

framework:
    session:
        storage_factory_id: session.storage.factory.php_bridge
        handler_id: session.handler.native_file

我取下了

var/cache
并加热了它。

结果:同上。

我尝试按照https://stackoverflow.com/a/44145831/4840661中的说明进行调试,错误遗留和Symfony给出相同的ini设置。

有什么想法如何使用 Symfony 读取我的案例中的遗留会话数据吗?

php symfony session
2个回答
0
投票

我会尝试以下方法:

您可以在 Symfony 中创建自定义会话处理程序

例如,您创建

CustomNativeSessionStorage
处理程序并继承
NativeSessionStorage
处理程序。当然,您也可以采用其他现有的处理程序并自定义它们。

CustomNativeSessionStorage::start()
方法中,您可以定义会话启动或加载的方式和时间。您当然可以使用 NativeSessionStorage::start() 的一部分来实现此目的。

NativeSessionStorage::start()
方法用于启动会话,然后您可以自己控制。


namespace App\Session;

use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

class CustomNativeSessionStorage extends NativeSessionStorage
{
    public function start(): bool
    {
        // Here is your logic
        return true;
    }
}
framework:
    session:
        # ...
        handler_id: App\Session\CustomNativeSessionStorage

0
投票

我发现自己处于同样的场景,我最终归档了这两个功能:

  • 将来自旧版应用程序的数据集成到 Symfony 会话中。
  • 保留旧应用程序未分组的 $_SESSION 数据,以避免破坏其会话。
<?php
namespace App\Session;

use LogicException;
use Override;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\SessionBagProxy;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

/**
 * This class integrates legacy session data with Symfony's AttributeBag ('_sf2_attributes').
 * Symfony groups its session data under specific $_SESSION keys (e.g., '_sf2_attributes').
 * The structure of the $_SESSION array is as follows:
 *
 *      $_SESSION = [
 *       // Legacy app's data, ungrouped:
 *       PHPSESSID = <value>,
 *       <key> = <value>,
 *       ...more values
 *       // Symfony session data, grouped:
 *       '_sf2_attributes' => [...],
 *       '_sf2_meta' => [...],
 *       '_symfony_flashes' => [...],
 *     ]
 *
 * NativeSessionStorage->loadSession() doesn't load the legacy data, and NativeSessionStorage->save() removes it.
 * Therefore, the aims of this class are:
 * - Integrate the data coming from the legacy app into the AttributeBag '_sf2_attributes'.
 * - Preserve the legacy app's ungrouped $_SESSION data to avoid breaking its session.
 */
class LegacySessionStorage extends NativeSessionStorage
{
    #[Override]
    protected function loadSession(?array &$session = null): void
    {
        parent::loadSession($session);
        
        // Filter legacy session data (keys not starting with '_s')
        $legacySessionData = array_filter($_SESSION, fn ($key) => !str_starts_with($key, '_s'), ARRAY_FILTER_USE_KEY);
        
        // Retrieve and validate the 'attributes' bag
        $attributesBagProxy = $this->getBag('attributes');
        if (!$attributesBagProxy instanceof SessionBagProxy) {
            throw new LogicException('Expected SessionBagProxy object, but found ' . get_class($attributesBagProxy));
        }
        
        $attributesBag = $attributesBagProxy->getBag();
        if (!$attributesBag instanceof AttributeBag) {
            throw new LogicException('Expected AttributeBag object, but found ' . get_class($attributesBag));
        }
        
        // Merge legacy data into Symfony's '_sf2_attributes'
        foreach ($legacySessionData as $key => $value) {
            $attributesBag->set($key, $value);
        }
    }
}

要使其工作,您需要一个特定的工厂类:

<?php

namespace App\Session;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorageFactory;
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;

use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;

class LegacySessionStorageFactory extends NativeSessionStorageFactory
{
    private array $options;
    private AbstractProxy|\SessionHandlerInterface|null $handler;
    private ?MetadataBag $metaBag;
    private bool $secure;
    
    public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null, bool $secure = false)
    {
        $this->options = $options;
        $this->handler = $handler;
        $this->metaBag = $metaBag ?? new MetadataBag();
        $this->secure = $secure;
    }
    
    public function createStorage(?Request $request): SessionStorageInterface
    {
        $storage =  new LegacySessionStorage($this->options, $this->handler, $this->metaBag);
        if ($this->secure && $request?->isSecure()) {
            $storage->setOptions(['cookie_secure' => true]);
        }
        return $storage;
    }
}

并将其注册到

framework.yml
:

session:
        storage_factory_id: session.storage.factory.legacy
        handler_id: ~
© www.soinside.com 2019 - 2024. All rights reserved.