PHP, nodeJS и сессии


У меня есть классический сервер apache, доставляющий php-файлы, и сервер nodeJS (с socket.io, но whithout express / connect) используется для управления событиями в реальном времени на этом веб-сайте PHP. Иногда мне нужно аутентифицировать клиентов, подключающихся к серверу nodeJS, но эта аутентификация теряется, когда пользователь перезагружает страницу, потому что она также перезагружает socket.io клиент (я храню идентификатор сокета на сервере, который теряется при каждом обновлении)
Вопрос в том, есть ли способ сохранить соединение живо внутри socket.io, или способ связать сессии Apache PHP и сервер nodeJS? Или, может быть, способ сохранить эту аутентификацию с помощью файлов cookie (зная, что я должен хранить конфиденциальные данные, такие как пароли пользователей и ключи)?

5 7

5 ответов:

Вы можете использовать memcached в качестве обработчика хранилища сеансов в PHP . Memcached-это простое хранилище значений ключей, доступ к которому можно получить по протоколу TCP; для узла доступен модуль memcached .js .

PHP сохраняет сеанс в memcached, используя идентификатор сеанса в качестве ключа. Данные сеанса (значение), хранящиеся в memcached, являются сериализованным объектом PHP, с небольшим искажением. Вы можете прочитать больше об этой необычной сериализации в так называемом " Parse PHP Session in Javascript " . К счастью, там уже есть модуль NPM: php-unserialize.


Теперь о том, как это сделать.

Предположения

  • memcached доступен по адресу 127.0.0.1: 11211
  • php.ini (или php.d / memcache.ini) настраивается с помощью: session.save_handler='memcached' и session.save_path='tcp://127.0.0.1:11211'
  • вы установили необходимые модули NPM (2): npm install memcached php-unserialize
  • вы в порядке с CLI

Подготовьте

Во-первых, просто чтобы получить некоторый тест данные для работы сохраните в следующем php скрипте (s.php):

<?php
session_start();
$_SESSION['some'] = 'thing';
echo session_id()."\n";
print_r($_SESSION);

Выполните его с php s.php, и он должен поместить материал в stdout:

74ibpvem1no6ssros60om3mlo5
Array
(
    [some] => thing
)

Хорошо, теперь мы знаем идентификатор сеанса (74ibpvem1no6ssros60om3mlo5) и подтвердили, что данные сеанса были установлены. Чтобы подтвердить, что он находится в memcached, вы можете запустить memcached-tool 127.0.0.1:11211 dump, который предоставляет дамп известных пар ключ: значение, например, у меня есть два в моем тестовом стенде:

Dumping memcache contents
  Number of buckets: 1
  Number of items  : 3
Dumping bucket 2 - 3 total items
add 74ibpvem1no6ssros60om3mlo5 0 1403169638 17
some|s:5:"thing";
add 01kims55ut0ukcko87ufh9dpv5 0 1403168854 17
some|s:5:"thing";

До сих пор мы 1) создали идентификатор сессии в php, 2) сохранили данные сессии из php в memcached, и 3) подтвердил, что данные существуют через CLI.

Извлечение с помощью узла.js

Эта часть на самом деле очень проста. Большая часть тяжелой работы уже выполнена модулями НПМ. Я приготовил маленький узел.JS скрипт, который работает через CLI, но вы получаете картинку:

var Memcached = require('memcached');
var PHPUnserialize = require('php-unserialize');

var mem = new Memcached('127.0.0.1:11211'); // connect to local memcached
var key = process.argv[2]; // get from CLI arg

console.log('fetching data with key:',key);
mem.get(key,function(err,data) { // fetch by key
        if ( err ) return console.error(err); // if there was an error
        if ( data === false ) return console.error('could not retrieve data'); // data is boolean false when the key does not exist
        console.log('raw data:',data); // show raw data
        var o = PHPUnserialize.unserializeSession(data); // decode session data
        console.log('parsed obj:',o); // show unserialized object
});

Предполагая, что выше сохранено как m.js, его можно запустить с node m.js 74ibpvem1no6ssros60om3mlo5, который выведет что-то вроде:

fetching data with key: 74ibpvem1no6ssros60om3mlo5
raw data: some|s:5:"thing";
parsed obj: { some: 'thing' }

Предупреждения / Gotchas

Одно из моих PHP-приложений хранит некоторые двоичные данные в значениях сеанса (т. е. зашифрованные), но ключи и обычный объект сеанса остаются нетронутыми (как в примере выше). В этом случае, memcached-tool <host:port> dump напечатал искаженную сериализованную строку сеанса в stdout; я думал, что это может быть изолировано в stdout, но я ошибся. при использовании PHPUnserialize.unserializeSession у него также возникли проблемы с разбором данных (разделенных |). Я попробовал несколько других методов десериализации сеанса в сети, но не имел никакого успеха. Я бы предположим, memcached поддерживает правильные данные внутри, так как он работает с собственным обработчиком сохранения сеанса PHP, поэтому на момент написания этой статьи я не совсем уверен, являются ли это методы десериализации или модуль memcached NPM просто не получает/интерпретирует данные правильно. При использовании небинарных данных, таких как ascii или utf-8, он должен работать так, как задумано.

Я думаю, что эта ссылка будет Вам полезна. https://simplapi.wordpress.com/2012/04/11/php-nodejs-session-share-memcache/

Хотя поток старый, я хотел бы порекомендовать то, что я использовал для своего проекта. Вместо memcached вы также можете использовать Redis для обработки сессии. Я использовал phpredis в качестве клиента PHP redis.Вместо сохранения сеанса в файлы вы можете сохранить его в Redis. Большая часть тяжелой работы будет выполнена апачами. Для каждого запроса apache будет добавлять значения сеанса в файлы cookie.И он считывает значения сеанса из каждого запроса и проверяет его.

Настройка, необходимая для сохранения PHP сессии в Redis тоже очень просто.

Сессия.save_handler = Рэдис сессия.save_path = " tcp: / / host1: 6379?вес=1, tcp: / / host2: 6379?weight=2 & timeout=2.5, tcp: / / host3: 6379?вес=2"

Вот и все.Это заставит php сохранять сессии в redis вместо файла. Это также переместит сеанс, сохраненный в файлах, в redis.

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

Если анализ в вашем конкретном случае показывает обещание, то node-mysql (или аналогичный) может быть использован-см. Это: link

Ответ отzamnuts помог мне сделать с момента выполнения аутентификации и был подходом, который я уже использовал. Спасибо тебе за это.

Причина, по которой я публикую, является для меня какой-то причиной при использовании:

var PHPUnserialize = require('php-unserialize');

Продолжал давать мне ошибку

SyntaxError: String length mismatch

Я не уверен, почему? Я написал функцию, которая делает эту работу за меня, и хотел поделиться, если это может помочь кому-то еще.

function Unserialize(data){

  var result = {};

  if(data !== undefined){

    var preg = data.replace(/(^|s:[0-9]+:)|(^|i:)|(^|b:)|(")|(;$)/g,'').split(';'); 

    var a = [];
    preg.forEach(function(value){
      a.push(value.split('|'));
    });

    var b = [];
    a.forEach(function(value){
      if(Array.isArray(value)){
        Array.prototype.push.apply(b, value);
      }else{
        b.push(value);  
      }
    });

    var arr_A = [];
    var arr_B = [];
    b.forEach(function(value, k){
      if(k % 2 == 0){
        arr_A.push(value);
      }else{
        arr_B.push(value);
      }     
     });


     if (arr_A == null) return {};

     for (var i = 0, l = arr_A.length; i < l; i++) {
       if (arr_B) {
        result[arr_A[i]] = arr_B[i];
       } else {
        result[arr_A[i][0]] = arr_A[i][1];
       }
     }

  }

  return result;

}

Я просто называю это так:

var PHPUnserialize = Unserialize;

memcached.get(key, function(err, data){
   var memData = PHPUnserialize(data);
   console.log(memData.is_logged_in);
}); 

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