首页 > 解决方案 > 当新用户连接之前的连接成为新用户

问题描述

我一直在玩 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');
});

我没有收到任何错误,它正确计算了用户数

问题是第一次登录的用户被切换到最后一次登录的用户

如何使用户会话独一无二,以便多个客户端可以登录到不同的帐户?

标签: node.jssocket.io

解决方案


我注意到一个问题:var userDataID; 它是一个全局变量。每次有新用户登录时,userDataID都会更新。它始终是最新登录用户的 ID。然后,所有新消息将使用 userDataID 存储在数据库中。EX: - 用账号 A 在窗口登录,userDataID = 1;- 向服务器发送一些消息,这些消息将存储在 userID = 1 - 在 iPhone 上使用帐户 B 登录,userDataID 将被更新,现在它 = 2。- 从windown & iphone 发送一些消息。所有这些消息都将使用 userID 2 存储。

我认为这是你得到的错误。

应将用户 ID 存储在 cookie 或会话中。


推荐阅读