Примеры прокси сессии

Механизм прокси сессии имеет множество применений, и эта статья демонстрирует два наиболее распространённых. Вместо того, чтобы использовать обычный обработчик сессий, вы можете создаь пользовательский, просто определив класс, расширяющий класс SessionHandlerProxy.

После этого, определите класс, как сервис. Если вы используете конфигурацию services.yml по умолчанию, это случится автоматически.

Наконец, используйте опцию конфигурации framework.session.handler_id, чтобы сказать Symfony использовать ваш обработчик сессии, вместо установленного по умолчанию:

  • YAML
    1
    2
    3
    4
    5
    # app/config/config.yml
    framework:
        session:
            # ...
            handler_id: AppBundle\Session\CustomSessionHandler
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <!-- app/config/config.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <framework:config>
            <framework:session handler-id="AppBundle\Session\CustomSessionHandler" />
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // app/config/config.php
    use AppBundle\Session\CustomSessionHandler;
    $container->loadFromExtension('framework', array(
        // ...
        'session' => array(
            // ...
            'handler_id' => CustomSessionHandler::class,
        ),
    ));
    

Продолжайте читать следующий раздел, чтобы узнать, как использовать обработчики сессиий на практике, чтобы решать два наиболее распространённых случая использования: шифрование информации о сессии и определение гостевых сессий только для чтения.

Шифрование данных сессии

Если вы хотите зашифровать данные сессии, вы можете использовать прокси для шифровки и расшифровки сессии:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// src/AppBundle/Session/EncryptedSessionProxy.php
namespace AppBundle\Session;

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

class EncryptedSessionProxy extends SessionHandlerProxy
{
    private $key;

    public function __construct(\SessionHandlerInterface $handler, $key)
    {
        $this->key = $key;

        parent::__construct($handler);
    }

    public function read($id)
    {
        $data = parent::read($id);

        return mcrypt_decrypt(\MCRYPT_3DES, $this->key, $data);
    }

    public function write($id, $data)
    {
        $data = mcrypt_encrypt(\MCRYPT_3DES, $this->key, $data);

        return parent::write($id, $data);
    }
}

Гостевые сессии только для чтения

Существуют приложения, где сессия требуется для гостевых пользователей, но где нет необходимости сохранять сессию. В этом случае, вы можете прервать сессию до того, как она будет записана:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// src/AppBundle/Session/ReadOnlySessionProxy.php
namespace AppBundle\Session;

use AppBundle\Entity\User;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class ReadOnlySessionProxy extends SessionHandlerProxy
{
    private $tokenStorage;

    public function __construct(\SessionHandlerInterface $handler, TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;

        parent::__construct($handler);
    }

    public function write($id, $data)
    {
        if ($this->getUser() && $this->getUser()->isGuest()) {
            return;
        }

        return parent::write($id, $data);
    }

    private function getUser()
    {
        if (!$token = $tokenStorage->getToken()) {
            return;
        }

        $user = $token->getUser();
        if (is_object($user)) {
            return $user;
        }
    }
}

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.