Аутентифицировать пользователя для socket.io/nodejs

У меня есть php login, пользователь вводит имя пользователя / пароль, он проверяет mysql db на данные входа. Если аутентификация сеанса создается через php, и теперь пользователь может получить доступ к системе с помощью php-сессии. Мой вопрос: после аутентификации через php / session будет ли процесс авторизации пользователя, чтобы узнать, имеют ли они права доступа для доступа к серверу nodejs с socket.io? Я не хочу, чтобы у человека был доступ к функции nodejs / socket.io / server, если они не прошли аутентификацию через логин php.

Обновить

Требования:

  1. Сначала выполните redis.
  2. Затем запустите socket.io.
  3. Наконец, загрузите / запустите PHP (есть зависимости в архиве).

Socket.io

var express = require('express'), app = express.createServer(), sio = require('socket.io'), redis = require("redis"), client = redis.createClient(), io = null; /** * Used to parse cookie */ function parse_cookies(_cookies) { var cookies = {}; _cookies && _cookies.split(';').forEach(function( cookie ) { var parts = cookie.split('='); cookies[ parts[ 0 ].trim() ] = ( parts[ 1 ] || '' ).trim(); }); return cookies; } app.listen(3000, "localhost"); io = sio.listen(app); io.of('/private').authorization(function (handshakeData, callback) { var cookies = parse_cookies(handshakeData.headers.cookie); client.get(cookies.PHPSESSID, function (err, reply) { handshakeData.identity = reply; callback(false, reply !== null); }); }).on('connection' , function (socket) { socket.emit('identity', socket.handshake.identity); }); 

PHP

php с аутентификацией openid => http://dl.dropbox.com/u/314941/6503745/php.tar.gz

После входа в систему необходимо перезагрузить client.php для аутентификации


ps: Мне действительно не нравится концепция создания еще одного пароля, который, вероятно, будет небезопасным. Я бы посоветовал вам взглянуть на openID (например, через Google ), Facebook Connect (просто назвать несколько вариантов).

Мой вопрос заключается в том, что после аутентификации через php / session будет выполняться проверка подлинности пользователя, чтобы узнать, имеют ли они права доступа для доступа к серверу nodejs с socket.io? Я не хочу, чтобы у человека был доступ к функции nodejs / socket.io / server, если они не прошли аутентификацию через логин php.

Добавьте уникальный session_id в список / набор допустимых идентификаторов, чтобы socket.io мог авторизовать (искать функцию авторизации) это соединение. Я бы позволил PHP общаться с node.js, используя redis, потому что это будет молниеносно / AWESOME :). Прямо сейчас я фальсифицирую сообщение PHP от redis-cli

Установите Redis

Загрузить redis => В настоящее время стабильная версия может быть загружена с: http://redis.googlecode.com/files/redis-2.2.11.tar.gz

 alfred@alfred-laptop:~$ mkdir ~/6502031 alfred@alfred-laptop:~/6502031$ cd ~/6502031/ alfred@alfred-laptop:~/6502031$ tar xfz redis-2.2.11.tar.gz alfred@alfred-laptop:~/6502031$ cd redis-2.2.11/src alfred@alfred-laptop:~/6502031/redis-2.2.11/src$ make # wait couple of seconds 

Начать Redis-сервер

 alfred@alfred-laptop:~/6502031/redis-2.2.11/src$ ./redis-server 

Socket.io

зависимости npm

Если npm еще не установлен, сначала посетите http://npmjs.org

 npm install express npm install socket.io npm install redis 

перечисление зависимостей, которые я установил, и которые вы также должны установить в случае несовместимости в соответствии с npm ls

 alfred@alfred-laptop:~/node/socketio-demo$ npm ls /home/alfred/node/socketio-demo ├─┬ express@2.3.12 │ ├── connect@1.5.1 │ ├── mime@1.2.2 │ └── qs@0.1.0 ├── hiredis@0.1.12 ├── redis@0.6.0 └─┬ socket.io@0.7.2 ├── policyfile@0.0.3 └── socket.io-client@0.7.2 

Код

server.js

 var express = require('express'), app = express.createServer(), sio = require('socket.io'), redis = require("redis"), client = redis.createClient(), io = null; /** * Used to parse cookie */ function parse_cookies(_cookies) { var cookies = {}; _cookies && _cookies.split(';').forEach(function( cookie ) { var parts = cookie.split('='); cookies[ parts[ 0 ].trim() ] = ( parts[ 1 ] || '' ).trim(); }); return cookies; } app.listen(3000, "localhost"); io = sio.listen(app); io.configure(function () { function auth (data, fn) { var cookies = parse_cookies(data.headers.cookie); console.log('PHPSESSID: ' + cookies.PHPSESSID); client.sismember('sid', cookies.PHPSESSID, function (err , reply) { fn(null, reply); }); }; io.set('authorization', auth); }); io.sockets.on('connection', function (socket) { socket.emit('access', 'granted'); }); 

Для запуска сервера просто запустите node server.js

client.php

 <?php session_start(); echo "<h1>SID: " . session_id() . "</h1>"; ?> <html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script> <script src="http://localhost:3000/socket.io/socket.io.js"></script> </head> <body> <p id="text">access denied</p> <script> var socket = io.connect('http://localhost:3000/'); socket.on('access', function (data) { $("#text").html(data); }); </script> </body> 

Проверка подлинности

Когда вы загружаете веб-страницу (PHP-файл) из своего веб-браузера, отображается access denied к сообщениям, но когда вы добавляете session_id также отображаемый в браузере для сервера redis, будет показан access granted к сообщению. Конечно, вы не будете делать копии, но просто позвольте PHP напрямую общаться с Redis. авт , Но для этой демонстрации вы поместите SID ramom807vt1io3sqvmc8m4via1 в redis, после чего будет предоставлен доступ.

 alfred@alfred-laptop:~/database/redis-2.2.0-rc4/src$ ./redis-cli redis> sadd sid ramom807vt1io3sqvmc8m4via1 (integer) 1 redis> 

Помните, что сеансы – это просто файлы, хранящиеся в каталоге php sessions. Для node.js не будет проблемой получить идентификатор сеанса из файла cookie, а затем проверить, действительно ли сеанс существует в каталоге сеансов. Чтобы получить путь к каталогу сеансов, обратитесь к директиве session.save_path в вашем php.ini.

Я сделал все это тяжело и не мог найти для меня жизнь, как затем получить значения хранения сеанса через то, что написал кто-то, поскольку все, что у вас осталось, – это значение хеша для вашего se. Поэтому я написал этот красивый маленький скрипт, который анализирует ваши значения сеанса в объекте.

 function unserialize_session(str){ var sessHash, sessHashEnd, sess = {}, serial = '', i =0; do { sessHash = str.match(/(^|;)([a-zA-Z0-9_-]+)\|/i); if (sessHash) { str = str.substring(sessHash[0].length); serial = str; sessHashEnd = serial.match(/(^|;)([a-zA-Z0-9_-]+)\|/i); if (sessHashEnd && sessHashEnd[2] && sessHashEnd[2].length > 0) { serial = serial.substring(serial.search(new RegExp('(^|;)('+sessHashEnd[2]+')\\|')),0); str = str.substring(str.search(new RegExp('(^|;)('+sessHashEnd[2]+')\\|'))) } sess[sessHash[2]] = unserialize(serial); } if (i++ > 50 ) break; } while (sessHash); return sess; } exports.unserialize_session = unserialize_session; 

К сожалению, чтобы получить значения PHP, сеансы должны были быть задействованы MySQL, чтобы получить доступ к ним легко, но эта часть зависит от вас, я думаю!

Вот код unserialize и utf8, если вы тоже этого хотите, изначально полученный из phpjs.org – пришлось немного его отредактировать, чтобы он работал с node.js, так что рыбу вокруг и сравнить, если вы хотите

 function utf8_decode (str_data) { // http://kevin.vanzonneveld.net // + original by: Webtoolkit.info (http://www.webtoolkit.info/) // + input by: Aman Gupta // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Norman "zEh" Fuchs // + bugfixed by: hitwork // + bugfixed by: Onno Marsman // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // * example 1: utf8_decode('Kevin van Zonneveld'); // * returns 1: 'Kevin van Zonneveld' var tmp_arr = [], i = 0, ac = 0, c1 = 0, c2 = 0, c3 = 0; str_data += ''; while (i < str_data.length) { c1 = str_data.charCodeAt(i); if (c1 < 128) { tmp_arr[ac++] = String.fromCharCode(c1); i++; } else if (c1 > 191 && c1 < 224) { c2 = str_data.charCodeAt(i + 1); tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); i += 2; } else { c2 = str_data.charCodeAt(i + 1); c3 = str_data.charCodeAt(i + 2); tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; } } return tmp_arr.join(''); } exports.utf8_decode = utf8_decode; function unserialize (data) { // http://kevin.vanzonneveld.net // + original by: Arpad Ray (mailto:arpad@php.net) // + improved by: Pedro Tainha (http://www.pedrotainha.com) // + bugfixed by: dptr1988 // + revised by: d3x // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Brett Zamir (http://brett-zamir.me) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Chris // + improved by: James // + input by: Martin (http://www.erlenwiese.de/) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Le Torbi // + input by: kilops // + bugfixed by: Brett Zamir (http://brett-zamir.me) // - depends on: utf8_decode // % note: We feel the main purpose of this function should be to ease the transport of data between php & js // % note: Aiming for PHP-compatibility, we have to translate objects to arrays // * example 1: unserialize('a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}'); // * returns 1: ['Kevin', 'van', 'Zonneveld'] // * example 2: unserialize('a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}'); // * returns 2: {firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'} var that = this; var utf8Overhead = function (chr) { // http://phpjs.org/functions/unserialize:571#comment_95906 var code = chr.charCodeAt(0); if (code < 0x0080) { return 0; } if (code < 0x0800) { return 1; } return 2; }; var error = function (type, msg, filename, line) { console.log('[[[[[[[[[[[[[[[[[[ERROR]]]]]]]]]]]]]]]]]]]','msg:', msg, 'filename:',filename, 'line:',line); }; var read_until = function (data, offset, stopchr) { if (stopchr == ';' && !data.match(/;$/)) data += ';'; var buf = []; var chr = data.slice(offset, offset + 1); var i = 2; while (chr != stopchr) { if ((i + offset) > data.length) { error('Error', 'Invalid','php.js','126'); } buf.push(chr); chr = data.slice(offset + (i - 1), offset + i); i += 1; //console.log('i:',i,'offset:',offset, 'data:',data,'chr:',chr,'stopchr:',stopchr); } return [buf.length, buf.join('')]; }; var read_chrs = function (data, offset, length) { var buf; buf = []; for (var i = 0; i < length; i++) { var chr = data.slice(offset + (i - 1), offset + i); buf.push(chr); length -= utf8Overhead(chr); } return [buf.length, buf.join('')]; }; var _unserialize = function (data, offset) { var readdata; var readData; var chrs = 0; var ccount; var stringlength; var keyandchrs; var keys; if (!offset) { offset = 0; } var dtype = (data.slice(offset, offset + 1)).toLowerCase(); var dataoffset = offset + 2; var typeconvert = function (x) { return x; }; switch (dtype) { case 'i': typeconvert = function (x) { return parseInt(x, 10); }; readData = read_until(data, dataoffset, ';'); chrs = readData[0]; readdata = readData[1]; dataoffset += chrs + 1; break; case 'b': typeconvert = function (x) { return parseInt(x, 10) !== 0; }; readData = read_until(data, dataoffset, ';'); chrs = readData[0]; readdata = readData[1]; dataoffset += chrs + 1; break; case 'd': typeconvert = function (x) { return parseFloat(x); }; readData = read_until(data, dataoffset, ';'); chrs = readData[0]; readdata = readData[1]; dataoffset += chrs + 1; break; case 'n': readdata = null; break; case 's': ccount = read_until(data, dataoffset, ':'); chrs = ccount[0]; stringlength = ccount[1]; dataoffset += chrs + 2; readData = read_chrs(data, dataoffset + 1, parseInt(stringlength, 10)); chrs = readData[0]; readdata = readData[1]; dataoffset += chrs + 2; if (chrs != parseInt(stringlength, 10) && chrs != readdata.length) { error('SyntaxError', 'String length mismatch','php.js','206'); } // Length was calculated on an utf-8 encoded string // so wait with decoding readdata = utf8_decode(readdata); break; case 'a': readdata = {}; keyandchrs = read_until(data, dataoffset, ':'); chrs = keyandchrs[0]; keys = keyandchrs[1]; dataoffset += chrs + 2; for (var i = 0; i < parseInt(keys, 10); i++) { var kprops = _unserialize(data, dataoffset); var kchrs = kprops[1]; var key = kprops[2]; dataoffset += kchrs; var vprops = _unserialize(data, dataoffset); var vchrs = vprops[1]; var value = vprops[2]; dataoffset += vchrs; readdata[key] = value; } dataoffset += 1; break; default: error('SyntaxError', 'Unknown / Unhandled data type(s): ' + dtype,'php.js','238'); break; } return [dtype, dataoffset - offset, typeconvert(readdata)]; }; return _unserialize((data + ''), 0)[2]; } exports.unserialize = unserialize;