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