gpt4 book ai didi

php - Drupal 8 覆盖 session 管理

转载 作者:可可西里 更新时间:2023-11-01 00:40:28 24 4
gpt4 key购买 nike

我想覆盖 drupals 核心 session 管理以支持我自己的,而不是将 session 保存到 Redis 而不是数据库。

在谷歌搜索之后,除了这个之外没什么可做的: https://www.drupal.org/project/session_proxy

唯一的问题是它与 Drupal 8 不兼容,我只想保存到 Redis,不需要任何其他处理程序。

在 Symfony 中,我创建了一个 session 处理程序服务,但在 Drupal 8 中似乎更加棘手。

关于我应该如何进行的任何建议?

谢谢

最佳答案

我认为在不依赖第 3 方模块或任何其他插件的情况下解决此问题的最简单方法是覆盖 Drupals 核心 SessionHandler 类。

首先,在我的模块中,我创建了一个 ServiceProvider 类,它指示容器用我自己的定义重新定义核心 SessionHandler 类定义。我不需要数据库连接服务,所以我确保只有请求堆栈被传递给构造函数。

<?php

namespace Drupal\my_module;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Symfony\Component\DependencyInjection\Reference;

class OoAuthServiceProvider extends ServiceProviderBase
{
/**
* {@inheritdoc}
*/
public function alter(ContainerBuilder $container)
{
$container->getDefinition('session_handler.storage')
->setClass('Drupal\my_module\SessionHandler')
->setArguments([
new Reference('request_stack')
]);
}
}

然后我开始创建自己的 Redis SessionHandler:

<?php

namespace Drupal\my_module;

use Drupal\Component\Utility\Crypt;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Utility\Error;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;

/**
* Default session handler.
*/
class SessionHandler extends AbstractProxy implements \SessionHandlerInterface {

use DependencySerializationTrait;

/**
* The request stack.
*
* @var RequestStack
*/
protected $requestStack;

/**
* @var \Redis
*/
protected $redis;

/**
* SessionHandler constructor.
*
* @param RequestStack $requestStack
*/
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
// TODO: Store redis connection details in config.
$this->redis = (new PhpRedis())->getClient('redis-host', 6379);
}

/**
* {@inheritdoc}
*/
public function open($savePath, $name)
{
return true;
}

/**
* {@inheritdoc}
*/
public function read($sid)
{
$data = '';

if (!empty($sid)) {
$query = $this->redis->get(Crypt::hashBase64($sid));
$data = unserialize($query);
}

return (string) $data['session'];
}

/**
* {@inheritdoc}
*/
public function write($sid, $value)
{
// The exception handler is not active at this point, so we need to do it
// manually.

var_dump(['Value', $value]);
try {
$request = $this->requestStack->getCurrentRequest();
$fields = [
'uid' => $request->getSession()->get('uid', 0),
'hostname' => $request->getClientIP(),
'session' => $value,
'timestamp' => REQUEST_TIME,
];

$this->redis->set(
Crypt::hashBase64($sid),
serialize($fields),
(int) ini_get("session.gc_maxlifetime")
);

return true;
}
catch (\Exception $exception) {
require_once DRUPAL_ROOT . '/core/includes/errors.inc';
// If we are displaying errors, then do so with no possibility of a
// further uncaught exception being thrown.
if (error_displayable()) {
print '<h1>Uncaught exception thrown in session handler.</h1>';
print '<p>' . Error::renderExceptionSafe($exception) . '</p><hr />';
}

return true;
}
}

/**
* {@inheritdoc}
*/
public function close()
{
return true;
}

/**
* {@inheritdoc}
*/
public function destroy($sid)
{
// Delete session data.
$this->redis->delete(Crypt::hashBase64($sid));

return true;
}

/**
* {@inheritdoc}
*/
public function gc($lifetime)
{
// Redundant method when using Redis. You no longer have to check the session
// timestamp as the session.gc_maxlifetime is set as TTL on write.
return true;
}

}

在我自己的 SessionHandler 实现中使用的 PhpRedis 只是一个用于处理连接到 Redis 的小实用程序类。

<?php

namespace Drupal\my_module;

/**
* Class PhpRedis
* @package Drupal\oo_auth
*/
class PhpRedis implements ClientInterface
{
/**
* {@inheritdoc}
*/
public function getClient($host = null, $port = null, $base = null, $password = null)
{
$client = new \Redis();
$client->connect($host, $port);

if (isset($password)) {
$client->auth($password);
}

if (isset($base)) {
$client->select($base);
}

// Do not allow PhpRedis serialize itself data, we are going to do it
// oneself. This will ensure less memory footprint on Redis size when
// we will attempt to store small values.
$client->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_NONE);

return $client;
}

/**
* {@inheritdoc}
*/
public function getName() {
return 'PhpRedis';
}
}

<?php

namespace Drupal\my_module;

/**
* Interface ClientInterface
* @package Drupal\oo_auth
*/
interface ClientInterface
{
/**
* Get the connected client instance.
*
* @param null $host
* @param null $port
* @param null $base
*
* @return mixed
*/
public function getClient($host = NULL, $port = NULL, $base = NULL);

/**
* Get underlying library name used.
*
* This can be useful for contribution code that may work with only some of
* the provided clients.
*
* @return string
*/
public function getName();
}

没有(我能找到的)建议文档向您提供如何使用 Redis(这实际上适用于任何数据存储)作为 Drupal 安装的 session 存储的示例。有一些关于如何启动它并与其他第 3 方模块一起运行的帖子,这很好,但我不想要多余的内容。

关于php - Drupal 8 覆盖 session 管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41486546/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com