Расширение сессий

Выкладываем свои наработки
Ответить
Аватара пользователя
radamir
Сообщения: 142
Зарегистрирован: 2009.08.10, 08:02
Откуда: Новосибирск

Расширение сессий

Сообщение radamir »

В реализации сессий в Yii нет возможности управлять привязкой сессии к IP или браузеру клиента, как это сделано в CI, а так же нет возможности управлять регенерацией ID сессии. И это бы было полбеды, можно ведь взять любой класс сессий и породить от него новый с нужным функционалом, но беда в том, что он относится ко всем классам сессий вне зависимости от реализованного ими бакэнда. Было бы вполне логично воспользоваться инфраструктурой behavior-ов, но увы, базовая реализация сессий не порождает ни одного события. Я не нашел ничего лучше как изменить код класса CHttpSession, вот так:

Код: Выделить всё

class CHttpSession extends CApplicationComponent implements IteratorAggregate,ArrayAccess,Countable
{
  public $bindingSignVar='BINDING_SIGN';
  public $bindingHasher='md5';

  protected $bindings=null;
  protected $bindingSign=null;
  protected $sidrProbability=0;
    
  public function setBindings($data)
  {
    foreach($data as $binding)
      $this->bindings[]=is_a($binding, 'CSessionBinding')?$binding:Yii::createComponent($binding);
  }
    
  public function setSIDRProbability($value)
  {
    $this->sidrProbability=min(100,max(0,(int)$value));
  }

  public function getBindingSign()
  {
    if($this->bindingSign===null)
    {
      $sign = '';
        foreach($this->bindings as $binding)
          $sign.=$binding->getSign();
        $this->bindingSign=$this->bindingHasher?call_user_func($this->bindingHasher,$sign):$sign;
    }
    return $this->bindingSign;
  }

  public function open()
  {
    if(session_id()==='')
    {
      if($this->getUseCustomStorage())
        session_set_save_handler(array($this,'openSession'),array($this,'closeSession'),array($this,'readSession'),array($this,'writeSession'),array($this,'destroySession'),array($this,'gcSession'));
      session_start();

      if($this->bindings!==null)
      {
        if($this->getCount()>0)
        {
          if($this->itemAt($this->bindingSignVar)==$this->getBindingSign())
          {
            if(mt_rand(0,100)<$this->sidrProbability)
              session_regenerate_id(true);
          }
          else
          {
            session_regenerate_id();
            session_unset();
            $this->add($this->bindingSignVar,$this->getBindingSign());
          }
        }
        else
          $this->add($this->bindingSignVar,$this->getBindingSign());
      }
    }
  }
}
 
Класс CSessionBinding:

Код: Выделить всё

class CSessionBinding extends CComponent
{
  protected $sign;
    
  public function getSign()
  {
    if($this->sign===null)
      $this->sign=$this->generateSign();
    return $this->sign;
  }
    
  protected function generateSign()
  {
    return '';
  }
}
 
И пара классов потомков, CUserIPSessionBinding:

Код: Выделить всё

class CUserIPSessionBinding extends CSessionBinding
{
  protected function generateSign()
  {
    return Yii::app()->request->userHostAddress;
  }
}
 
И CUserAgentSessionBinding:

Код: Выделить всё

class CUserAgentSessionBinding extends CSessionBinding
{
  protected function generateSign()
  {
    return Yii::app()->request->userAgent;
  }
}
 
А вот так может выглядеть конфигурация:

Код: Выделить всё

  'components'=>array(
    'session'=>array(
      'class'=>'CHttpSession',
      'bindings'=>array(
        'CUserIPSessionBinding',
        'CUserAgentSessionBinding'
      ),
      'bindingHasher'=>'crc32',
      'sidrProbability'=>10
    )
  )
 
Может есть более изящный вариант реализации этого, без вмешательства в базовый класс?
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Расширение сессий

Сообщение samdark »

Есть:

Код: Выделить всё

'components'=>array(
    'session'=>array(
      'class'=>'MyHttpSession',
      //…
  )
 

Код: Выделить всё

class MyHttpSession extends CHttpSession {
  // тут перекрываем нужные методы
}
 
Аватара пользователя
radamir
Сообщения: 142
Зарегистрирован: 2009.08.10, 08:02
Откуда: Новосибирск

Re: Расширение сессий

Сообщение radamir »

Если я решу изменить бакенд сессий, взяв один из уже реализованных в Yii, мне достаточно будет изменить одну строчку в конфигурации, вот так:

Код: Выделить всё

  'components'=>array(
    'session'=>array(
      'class'=>'CDbHttpSession',
      'bindings'=>array(
        'CUserIPSessionBinding',
        'CUserAgentSessionBinding'
      ),
      'bindingHasher'=>'crc32',
      'sidrProbability'=>10
    )
  )
 
Ты же предлагаешь мне отнаследоваться от CDbHttpSession и реализовать дополнительный функционал. И это я буду должен делать вновь и вновь с разными потомками CHttpSession реализующих разные бакенды. Причем это будет всегда один и тот же код.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Расширение сессий

Сообщение samdark »

А кто мешает отнаследоваться от MyHttpSession, а не от CHttpSession?
Аватара пользователя
radamir
Сообщения: 142
Зарегистрирован: 2009.08.10, 08:02
Откуда: Новосибирск

Re: Расширение сессий

Сообщение radamir »

А кто мешает отнаследоваться от MyHttpSession, а не от CHttpSession?
И заново реализовать все то что уже реализовано в CDbHttpSession и CCacheHttpSesion?
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Расширение сессий

Сообщение samdark »

В этом случае да… можно попробовать написать фич-реквест: http://code.google.com/p/yii/issues/list
Ответить