node.js - 当新用户连接之前的连接成为新用户
问题描述
我一直在玩 NodeJS 和最近的 socket.IO,我来自 PHP 开发并尝试真正了解如何使用 Node 和 socket.IO
我开始构建一个聊天应用程序,当我要在不同的设备上对其进行测试时,我注意到当我通过手机登录另一个帐户时,浏览器窗口会更新并获得与我在手机上登录相同的用户
索引.html
<!DOCTYPE html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: 0.5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<div id="chatLogin">
<input type="text" name="password" id="username" placeholder="Username..." /><br>
<input type="password" name="password" id="password" placeholder="Password..." /><br>
<button id="chatLoginBtn">Login / Register</button>
</div>
<div id="chatWindow">
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$(function () {
var socket = io();
$(document).ready(function(){
$("#chatWindow").hide();
$("#chatLoginBtn").click(function(){
socket.emit('loginForm', {
username: $("#username").val(),
password: $("#password").val()
});
});
});
socket.on('returnValue', function(msg) {
var html = '<ul id="messages"></ul>' +
'<form id="sendMsg" action="">' +
'<input id="m" autocomplete="off" /><button>Send</button>' +
'</form>';
$("#chatLogin").html("").hide();
$("#chatWindow").html(html).show();
$('#sendMsg').submit(function(e) {
e.preventDefault(); // prevents page reloading
var time = Date.now();
var msg = $("#m").val();
var data = [time, msg];
socket.emit('chat', data);
$('#m').val('');
return false;
});
});
socket.on('chat', function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
</body>
</html>
index.js
var app = require('express')();
var http = require('http').createServer(app);
var phpPass = require('node-php-password');
var mysql = require('mysql');
var io = require('socket.io')(http);
var cookieParser = require('cookie-parser');
var session = require('express-session');
// DECLARE the variables we will be using
// These does not change
let userCount = 0;
// These are declared to be later set
var displayName;
var userDataID;
// POOL MySQL Connection
var pool = mysql.createPool({
connectionLimit : 100,
host : 'localhost',
user : 'root',
password : '....',
port : '3306',
database : '....',
debug : false
});
// session & cookieParser
/*var sessionMiddleware = session({
secret: "keyboard cat"
});
io.use(function (socket, next) {
sessionMiddleware(socket.request, socket.request.res, next);
});
app.use(sessionMiddleware);
app.use(cookieParser());*/
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
var hashPassword;
function checkUser(user, Password, userID) {
pool.getConnection(function(error,connection) {
connection.query("SELECT password FROM accounts WHERE `username` = '"+user+"' LIMIT 1",function(error,rows){
if (!error) {
var hashPassword = rows[0].password;
if (phpPass.verify(Password, hashPassword)) {
console.log(Password);
console.log(hashPassword);
console.log("Went well");
// UPDATE user database with current socketID
connection.query("UPDATE accounts SET `socketID` = '"+userID+"' WHERE `username` = '"+user+"'",function(error,result){
connection.release();
if (!error) {
connection.query("SELECT id,displayName,username,email,fullName,dateofBirth,created,lastSignedIn FROM accounts WHERE socketID = '"+userID+"' LIMIT 1",function(error,userData){
if (!error) {
displayName = userData[0].displayName;
userDataID = userData[0].id;
console.log("Current user: " + userData[0].displayName);
} else {
console.log("Error" + error);
}
});
console.log("No error" + result);
} else {
console.log("We found error" + error);
}
});
// send to function to gather all needed info from database and save for the current session
return true;
} else {
console.log("Wrong pass");
return false;
}
console.log(hashPassword);
} else {
console.log(error);
return false;
}
});
connection.on('error', function(error) {
});
});
return true;
};
io.on('connection', (socket) => {
var req = socket.request;
var userID = socket.id;
// When connection is inited
userCount++;
console.log('User connected' + userCount);
// Take the data from login and pass to check if it is valid
socket.on("loginForm", function(data){
const user = data.username,
pass = data.password;
//console.log(checkUser(user, pass));
if (checkUser(user, pass, userID)) {
io.emit('returnValue', 'hi');
}
});
function joinRoom(room) {
socket.join(room);
console.log("Joined " + room);
return io.emit('chat', "Joined new room " + room);
}
socket.on('join', (data) => {
socket.join(data);
console.log("Joined " + data);
});
socket.on('chat', (data) => {
/* Array: Data;
[0] Time
[1] Message
[2] socketID
[3] User
*/
var msg = data[1];
var time = data[0];
// Calc time
var date = new Date(time);
var hours = date.getHours();
var minutes = date.getMinutes();
var formatted = hours + ":" + minutes;
if (minutes < 10) return minutes = "0" + minutes;
var dateFormatted = "[" + formatted + "] ";
//data.push(user);
pool.getConnection(function(error,connection) {
connection.query("INSERT INTO `chat_messages` (userID, socketID, message, time) VALUES ('"+userDataID+"', '"+userID+"', '"+msg+"', '"+time+"')",function(error,rows){
connection.release();
if (!error) {
console.log("Success");
} else {
console.log(error);
}
});
});
if (msg.startsWith('/me')) return io.emit('chat', dateFormatted + displayName + msg.substring(3));
if (msg.startsWith('/join')) return joinRoom(msg.substring(6));
if (msg.startsWith('/rooms')) return console.log(io.sockets.adapter.rooms);
return io.emit('chat', dateFormatted + displayName + ' said: ' + msg);
//console.log(displayName + 'said:' + msg);
});
// When user disconnects
socket.on('disconnect', () => {
userCount--;
console.log('User disconnected!' + userCount);
});
});
http.listen(3000, () => {
console.log('Listening on *:3000');
});
我没有收到任何错误,它正确计算了用户数
问题是第一次登录的用户被切换到最后一次登录的用户
如何使用户会话独一无二,以便多个客户端可以登录到不同的帐户?
解决方案
我注意到一个问题:var userDataID;
它是一个全局变量。每次有新用户登录时,userDataID
都会更新。它始终是最新登录用户的 ID。然后,所有新消息将使用 userDataID 存储在数据库中。EX: - 用账号 A 在窗口登录,userDataID = 1;- 向服务器发送一些消息,这些消息将存储在 userID = 1 - 在 iPhone 上使用帐户 B 登录,userDataID 将被更新,现在它 = 2。- 从windown & iphone 发送一些消息。所有这些消息都将使用 userID 2 存储。
我认为这是你得到的错误。
应将用户 ID 存储在 cookie 或会话中。
推荐阅读
- c++ - 如何从 C++17 以外的目录中读取 txt 文件(未知名称)?
- javascript - Socket.io 不向特定用户发送消息
- firebase - 尝试使用 Firebase 和 Github Pages 进行部署,但两个页面都是空白的
- javascript - 将 ES2019 转换为 React JSX
- powershell - 如何使用 powershell 将从图形 api 获取的用户个人资料照片保存到文件
- java - 更正应包含单个兼容版本的应用程序的类路径
- javascript - javascript, Hugo:将无序列表转换为 JSON
- python - 处理 Python 函数中参数无效导致的 NameErrors
- python - Postgres (psycopg2) 阻止用户更改运行时配置参数
- python - 如何获得捷径的真实路径