2017-01-05 4 views
2

drupals 핵심 세션 관리를 재정의하여 내 세션 대신 데이터베이스에 저장하는 대신 세션을 Redis에 저장합니다. 이 https://www.drupal.org/project/session_proxyDrupal 8 세션 관리 무시

유일한 문제는 그 드루팔 (8)와 호환되지 않습니다이고 나는 단지 내가 다른 처리기가 필요하지 않습니다 레디 스에 저장하려는 :

인터넷 검색 후이 제외에 갈 정도가 아니다 .

내가 세션 핸들러 서비스를 만들었지 만 드루팔 (8)

내가 진행하는 방법에 대한 어떤 제안에 훨씬 더 까다로운 것 같다 심포니에서

?

감사합니다.

답변

3

타사 모듈이나 다른 플러그인에 의존하지 않고이 문제를 해결하는 가장 간단한 방법은 Drupals 핵심 SessionHandler 클래스를 재정의하는 것입니다.

먼저 내 모듈에서 컨테이너에 내 SessionHandler 클래스 정의를 다시 정의하도록 지시하는 ServiceProvider 클래스를 만들었습니다. 요청 스택 만 생성자에 전달되도록 확실히하기 위해 데이터베이스 연결 서비스가 필요하지 않았습니다.

<?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') 
      ]); 
    } 
} 

나는 다음 내 자신의 레디 스 SessionHandler을 만들 진행하십시오 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; 
    } 

} 

PhpRedis은 레디 스 연결을 다루는 단지 작은 유틸리티 클래스입니다.

<?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(); 
} 

거기에 어떤 제안 설명서 (I 찾을 수) 당신 레디 스를 사용하는 방법의 예를 제공한다는 없다 (이 것 어떤 데이터 저장소와 사실 작업에서) 당신의 드루팔 설치를위한 세션 저장소로. 그것을 얻고 다른 제 3 자 모듈로 실행하는 방법에 대한 글이 있지만 괜찮지 만 나는 여분의 보풀을 원하지 않았다.

+0

안녕하세요, 칼, 당신은 귀하의 모듈과 지퍼가 있으시겠습니까? Drupal 프로젝트에서 구현할 수 있는지보고 싶습니다. –

+0

안녕하세요, André, 저는 이전 회사와 마찬가지로 불행하지 않습니다. 그러나 도움이 필요하시면 저에게 이메일을 보내 주시기 바랍니다. 그리고 최선을 다해 도와 드리겠습니다 : [email protected] :) – Kal

2

Redis 모듈의 알파 버전이 있습니다. 현재의 한계가 쇼 스토퍼가 아니라면 이것을 사용하고 문서화 된대로 구성 할 수 있습니다. https://www.drupal.org/project/redis

는 구성 설정에 대한 자세한 내용의 문서를 볼 수 있지만 선발로 모듈을 설치 한 후 당신은 당신의 settings.php에 이런 식으로 뭔가를 추가

$settings['cache']['default'] = 'cache.backend.redis'; 
$settings['redis.connection']['host'] = '<<redis_host>>'; 
$settings['redis.connection']['port'] = '<<redis_port>>'; 

어디 redis_host '와'redis_port ' Redis 인스턴스에 따라 설정됩니다.

+1

나는 "캐시"라고 말하지만 redis로 세션을 유지하겠습니까? – Kal

+0

이 Redis 모듈에 동일한 문제가 있습니다. 나는 캐시를 위해 Redis를 사용하여 그 결과를 얻었으며 훌륭하게 작동합니다. 그러나 Redis에서 세션을 얻으려고하는 데 여전히 운이 없다. –

+0

D8 Redis 모듈의 현재 릴리스는 세션을 지원하지 않지만 하위 모듈에 대한 작업이 있습니다. 이 스레드를 참조하십시오 https://www.drupal.org/project/redis/issues/2876099 –