Обновить сеанс другого пользователя - лучшая практика? - PullRequest
4 голосов
/ 16 декабря 2010

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

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

Но иногда сеанс пользователя необходимо обновлять на основе действий другого пользователя. Например, модератор обновляет права пользователя. Модератор не имеет доступа к пространству сеанса пользователя, поэтому обычные функции обновления не могут быть запущены для затронутого пользователя.

Я рассмотрел несколько способов принудительного обновления сеанса другого пользователя, но все они имеют недостатки:

  • Я мог бы искать и удалять их сеанс из таблицы сессий, но это требует полного сканирования таблицы (где sessdata, как "% user_id%"), и это может привести к потере содержание, которое может затронуть пользователь занимается генерацией.
  • Я мог бы принудительно обновить сессию периодически, например, когда sess_time_to_update срабатывает. Но нет никаких гарантий, что это будет происходить до пользователя пытаясь получить доступ к функциональность, для которой обновление необходимо.
  • Я мог бы запустить полную серию обновления переменных на каждой странице загрузки, но весь смысл поддержания сессия, чтобы избежать этих накладных расходов.
  • Я мог бы установить флаг, указывающий на необходимость для обновления сеанса, но этот сигнал должно быть опрошено при каждом выполнении страницы и в каждом контроллере. (Я знаю, что мог бы расширить CI_Controller как MY_Controller, но я не хочу этого делать)
  • Я уже отправляю пользователю электронное письмо уведомляя их об изменении разрешение, и это достаточно легко заставить их щелкнуть ссылку обновления сеанса (или даже выйдите и войдите снова). Но нет никакой гарантии, что они собираюсь даже читать вне темы линия, не говоря уже на самом деле нажмите на ссылка.

Так я что-то пропустил? Я ищу волшебную пулю, которой не существует?

(Обратите внимание, что я пометил это с помощью CodeIgniter и сделал ссылку на технические детали, относящиеся к CI, потому что это то, что я использую. Тем не менее, это не относится к CI (или даже к PHP) ) выпуск.)

Спасибо за помощь!

Ответы [ 4 ]

3 голосов
/ 16 декабря 2010

Ну, один из вариантов - установить номер версии ACL (либо для всех пользователей, либо для каждого пользователя). Затем при инициализации сеанса (ну, когда вы вызываете session_start()), проверьте, соответствует ли сохраненная версия версии сеанса. Если это не так, обновите ACL.

Еще один немного другой способ - добавить столбец в таблицу сеансов («статус» или «грязный» и т. Д.). Затем вместо того, чтобы убивать сеанс, просто обновите этот статус до 1. Затем при загрузке сеанса проверьте этот флаг, чтобы увидеть, равен ли он 1. Если это так, перезагрузите кэшированные данные в сеансе и установите для него значение 0. Если нет, продолжайте ...

Что касается обновления сеанса другого пользователя, я бы этого не делал ... Если сеансы управляются PHP, то вам нужно будет прервать текущий сеанс и запустить тот, который вы хотите изменить. Это просто напрашивается на проблемы ... (вам нужно это сделать, поскольку механизм PHP не использует сериализацию.).

Что касается удаления их сеанса, я бы не стал беспокоиться о полном сканировании таблицы. Если у вас не будет ТОНИ пользователей, постоянно обновляющих разрешения, это не будет иметь значения. Потеря данных является серьезной проблемой, так что эта идея лишена смысла ...

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

2 голосов
/ 16 декабря 2010

Я собираюсь сделать удар, хотя мой подход не совсем применим к Code Igniter.

Способ, которым я решил эту проблему в прошлом, состоит в том, чтобы создать объектную модель User с конструкторомэто берет UserID из первичного ключа базы данных, где хранятся учетные данные.Я напишу статический метод входа в систему, который проверяет учетные данные входа в систему, а затем создает экземпляр и возвращает экземпляр пользователя, если имя входа правильно для строки, а затем устанавливает сеанс.

Пока все хорошо, верно?Таким образом, все ваши разрешения, уровни доступа и т. Д. Хранятся в базе данных.Точно так же, как метод входа в систему, у нас может быть метод обновления, который восстанавливает объект, повторно выбирая из базы данных уже полученный первичный ключ.

class User{
public function __construct($uid){
  //fetch from the db here
  $sql = 'SELECT FROM User_Table WHERE UserID = ?';
  $params = array($uid);
  //fetch and assign using your flavor of database access, I use PDO
  //set all your object properties for access, as well as user_id, something like 
  //$this->user_id = $result['UserID'];
}

public static function Login($uname, $pass){
  $sql = 'SELECT UserID FROM User WHERE Username = ? AND Password = ?';
  $params = array($uname, md5($pass));
  //again I'm going to employ pseudocode here, fetch according to your preferred system
  if(!empty($result)){
    $_SESSION['user'] = new User($result['UserID']);
  }else{
     //login failed!
     return false;   
  }
}

final public function _refresh(){
  //refresher method.  Since the controller sets all the object properties for access
  //reconstructing and assigning it refreshes these priveliges.
  $_SESSION['user'] = new User($this->user_id);
  }

}

Используя эту модель, всякий раз, когда я выполняю действиес пользователем в сеансе, который потенциально может нуждаться в чувствительных ко времени разрешениях, я могу вызвать обновление объекта пользователя, все готово в сеансе.Допустим, у нас есть функция контроллера для доступа к закрытой форме.

function _topSecret(){
$_SESSION['user']->refresh();

if($_SESSION['user']->specific_permission_from_db){
  //Perform the special action, get the view, whatever.
}else{
  //redirect to an error page
}

}

Итак, если у вас уже есть подпрограммы, написанные для администраторов, все, что им нужно сделать, - это установить права пользователя в базе данных, и когдаМетод refresh работает с определенными, чувствительными ко времени функциями, эти данные будут помещены в сеанс для пользователя.Таким образом, вы не обязательно обновляете другой сеанс пользователя , вы просто определяете, какие действия настолько хронологически чувствительны, что им требуются новейшие разрешения, и выдает эту команду объекту пользователя в сеансе.

Это оказалось довольно эффективным для меня, так как реконструкция должна выполняться только для действий, которые требуют самых последних разрешений.Опять же, я не уверен, насколько это может быть полезно в контексте CI и вашего отдельного приложения, но я решил поделиться.Я предполагаю, что вы уже выполнили все необходимые меры безопасности сеанса и начали сеанс - большинство фреймворков, таких как CI, справятся с этим с помощью собственных средств.

1 голос
/ 16 декабря 2010

Добавить столбец в таблицу сеанса, который может содержать первичный ключ объекта пользователя. Установите его при входе в систему и используйте позже для обновления сеанса.

Редактировать: Если вы не хотите расширять таблицу сеансов, создайте дополнительную таблицу поиска, в которой у вас есть идентификатор объекта пользователя и ссылка на ключ сеанса.

0 голосов
/ 16 декабря 2010

Если вы сохраняете сеанс как нативный php-сеанс, я бы хотел оставить его в покое и позволить им получить какое-то уведомление о том, что им нужно войти / выйти, чтобы обновить настройку. У меня также были сайты, на которых данные сеанса хранятся в БД, а затем гораздо проще написать новую настройку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...