我有一个无法解释的问题。这就是我想要的:
- 客户端通过socket.io连接到节点服务器,发送他的SID
- Redis 验证该 SID 是否在其存储区中,如果没有,则不发出 'authenticated',如果 sid 在存储区中,则发出 'authenticated'
- 收到身份验证后,会给出额外的选项
听起来很简单,而且应该如此。但是会发生这种情况:
- 客户端连接到 redis 存储中的 SID
- Node.js 服务器验证 SID 是否在商店中,但未能发出所述“已验证”
但是,当我重新启动节点服务器时,一切似乎都很好:S。但是,当我继续从商店中删除密钥并再次添加它(通过 ?auth 和 ?logout)时,再次不会发出“已验证”。
客户端代码:
<?php
session_start();
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
require "./libraries/Predis.php";
if(isset($_GET['logout'])) {
session_regenerate_id();
}
$sid = sha1(session_id());
$redis = new Predis\Client();
echo "<h1>SID: " . $sid . "</h1>";
if(isset($_GET['auth'])) {
$redis->set($sid, mt_rand(1,20000));
$redis->expire($sid, 1800);
echo "auth set<br />";
}
if ($redis->get($sid)) {
// he is authenticad, show something else
echo "auth found<br />";
}
?>
<html>
<head>
<title>Node Test VTclient</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script src="http://the_server.dev:11337/socket.io/socket.io.js"></script>
</head>
<body>
<p id="text">access denied</p>
<script type="text/javascript">
var connected = false;
var authenticated = false;
if(typeof io == 'undefined') {
trigger_error();
} else {
var socket = io.connect('http://vtvserver.dev:11337/', {
'reconnection delay' : 1,
'max reconnection attempts' : 1
});
socket.on('connect', function (data) {
connected = true;
socket.emit('success_connect',{sid: '<?php echo $sid; ?>'});
$('#text').html('connected');
socket.on('get_bids', function (data) {
$('#bids').html('');
if(typeof data === 'object') {
$.each(data.rows, function(key, value) {
add_bid(value.bid_id, value.bid_amount);
});
}
}).on('reconnecting', function (reason) {
trigger_error(reason);
$('#text').html('disconnected');
socket.disconnect();
}).on('authenticated', function(data) {
$('#text').html('authorised!');
// successful auth
$('#bidding').show();
}).on('disconnect', function (data) {
connected = false;
}).on('bid_placed', function (data) {
add_bid(data.id, data.amount);
}).on('own_bid_placed', function(data){
if(!data.error) {
alert('bieding geplaatst!');
} else {
alert('Uw bieding is ongeldig.');
}
});
});
}
function trigger_error(reason) {
$('#text').html('Server is down...');
}
function add_bid(id, amount) {
$('#bids').append($('<option>', { value : id }).text(amount));
}
$(function() {
$('#disconnect').click(function() {
if(connected === true) {
socket.disconnect();
$('#text').html('Disconnected from server.');
}
});
$('#bid').click(function() {
var amount = $('#amount').val();
// commit the bid to the server
socket.emit('add_bid', {amount: amount});
});
})
</script>
<label for="bids">Biedingen:</label>
<select name="bids" id="bids" multiple='multiple' style='width:100px; height:150px'></select>
<fieldset style="display:none" id="bidding">
<legend>Plaats bieding</legend>
<label for="amount"><Bedrag: </label><input type="text" id="amount" name="amount" value='0' />
<button id="bid">Bied</button>
</fieldset>
<button id="disconnect">Disconnect</button>
</body>
服务器代码:
var
cfg = require("./config").cfg(),
sys = require("sys"),
url = require("url"),
http = require("http"),
qs = require("querystring"),
redis = require("redis"),
redis_client = redis.createClient(cfg.redis.port, cfg.redis.host),
express = require("express"),
mysql = require("./node_modules/mysql"),
//ch = require("./node_modules/channel").channel(cfg.msg_backlog, cfg.msg_truncate),
sio = require('./node_modules/socket.io');
//require ('./node_modules/sherpa');
//require ('./node_modules/log');
require ('./node_modules/simplejsonp');
redis_client.on("error", function (err) {
console.log("REDIS error: " + err);
});
var app = express();
app.configure(function(){
});
app.get('/',
function (req,res) {
if (req.headers['referer']) {
log(req.connection.remoteAddress + " / " + req.headers['referer']);
}
else {
log(req.connection.remoteAddress + " /");
}
res.writeHead(307, {'Location':'http://' + cfg.domain});
res.end();
});
app.listen(cfg.server_port, cfg.server_public_ip);
/* Create the IO server */
var server = http.createServer(app);
var io = sio.listen(server);
// minify the browser socket io client
io.enable('browser client minification');
server.listen(11337);
io.set('log level', 2);
io.sockets.on('disconnect', function(data) {
console.log('client disconnected');
});
/**
* Enable authentication
* @param {[type]} handshakeData [description]
* @param {Function} callback [description]
* @return {[type]} [description]
*/
// Anonymous or authenticaed user?
io.on('connection', function (socket) {
var sql_client = mysql.createClient({
host : cfg.database.server,
user : cfg.database.user,
password : cfg.database.pass,
database : cfg.database.primary
});
console.log('incoming connection');
socket.emit('access', 'granted');
socket.on('success_connect', function(data) {
console.log('Client connected: ' + data.sid);
sql_client.query('SELECT * FROM `bids`',function(error, results) {
if(error) {
console.log('Error: ' + error);
return false;
}
console.log('emitting get_bids...');
socket.emit('get_bids', {rows: results});
});
// if the user is authenticated, flag it as such
redis_client.get(data.sid, function(err, reply) {
var authenticated = false;
if(err) {
console.log("Fatal error: " + err);
}
console.log('Got response from redis...');
if(reply !== null) {
console.log('auth succesful for '+data.sid);
socket.emit('authenticated', { sid : data.sid});
authenticated = true;
}
// LEFT JOIN user_bids ON user_bids_bid_id = bid_id
if(authenticated === true) {
// safest way: only listen for certain commands when the user is autenticated
socket.on('add_bid', function(data) {
var amount = data.amount;
var values = [amount];
var error = false;
// validate the amount
var regexp = new RegExp(/^\d{1,5}(\.\d{1,2})?$/);
if(typeof amount === 'undefined' || amount < 1.00 || !amount.match(regexp)) {
error = 'invalid_bid';
}
socket.emit('own_bid_placed', {amount: amount, error : error});
if(!error) {
sql_client.query('INSERT INTO `bids` SET bid_amount = ?',values,function(error, results) {
if(error) {
console.log('Error: ' + error);
}
console.log('Inserted: ' + results.affectedRows + ' row.');
console.log('Id inserted: ' + results.insertId);
io.sockets.emit('bid_placed', {id: results.insertId, amount: amount});
});
}
});
}
});
});
sql_client.end();
socket.on('disconnect', function(data) {
console.log('Client disconnected');
});
});
console.log('Server running at http://'+cfg.server_public_ip+':'+cfg.server_port+'/');