代码之家  ›  专栏  ›  技术社区  ›  Gabriel

护照SocketIo-如何使用NodeJS、Express和Passport获取在线用户列表

  •  11
  • Gabriel  · 技术社区  · 8 年前

    我完成了 sessionStore 具有 MongoStore 每个登录都正确执行,会话都被写入数据库,没有错误。我正在使用此软件包 github.com/jfromaniello/passport.socketio 将passport与socket io对齐,但我已经查找了几个关于如何在登录后处理 sessionStorage 所以它列出了哪些名字的用户是在线的和离线的,可以告诉我一点吗?

    应用程序。js公司

    var express = require('express');
    var mongoose = require('mongoose');
    var path = require('path');
    var bodyParser = require('body-parser');
    var cookieParser = require('cookie-parser');
    var session = require('express-session');
    const MongoStore = require('connect-mongo')(session);
    var flash = require('connect-flash');
    var logger = require('morgan');
    var passport = require('passport');
    
    var passportSetup = require('./passport-setup');
    
    // import routes
    var routes = require('./routes');
    
    // setup express app
    var app = express();
    app.use(logger());
    
    // setup connection with mongodb
    mongoose.connect( process.env.MONGODB_URI || "mongodb://smachs:***@d***.mlab.com:****/****-messenger",
        (err, db)=> {
            if (err) return new Error(err);
            console.log('🔐  Conexão estabelecida com banco de dados!');
        });
    // setup passport from different class        
    passportSetup(); 
    
    // set view engine and connection of application
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'ejs');
    app.use(bodyParser.urlencoded({extended:false}));
    app.use(cookieParser());
    
    // session storage based in mongodb
    var sessionStore = new MongoStore({
        url: 'mongodb://smachs:***@d***.mlab.com:****/****-messenger',
        ttl: 1 * 24 * 60 * 60, // = 1 days. Default
        autoReconnect: true
    })
    
    // setup session based in express-session
    app.use(session({
        secret:"58585858585858",
        key: "connect.sid",
        resave: false,
        saveUninitialized: false,
        store: sessionStore
    }));
    
    app.use(flash());
    
    // public directory
    app.use(express.static(__dirname + '/public'));
    
    // passport staff
    app.use(passport.initialize());
    app.use(passport.session());
    
    // start routes
    app.use(routes);
    
    // start server
    var port = process.env.PORT || 3000;
    var server = app.listen(port, () => { console.log('🌐  Servidor iniciado em localhost:', port); });;
    
    // setup socket.io and passport.socketio packages
    var io = require('socket.io').listen(server);
    var passportSocketIo = require("passport.socketio");
    
    // setup session found in express-session
    io.use(passportSocketIo.authorize({
        cookieParser: cookieParser,       // the same middleware you registrer in express
        key: 'connect.sid',       // the name of the cookie where express/connect stores its session_id
        secret: '58585858585858',    // the session_secret to parse the cookie
        store: sessionStore, // we NEED to use a sessionstore. no memorystore please
        success: onAuthorizeSuccess,  // *optional* callback on success - read more below
        fail: onAuthorizeFail,     // *optional* callback on fail/error - read more below
    }));
    
    // setup route just for clients authenticate
    function ensureAutheticated(req, res, next) {
        if (req.isAuthenticated()) next();
        else {
            req.flash("info", "Você precisa estar logado para visualizar essa página!");
            res.redirect('/login');
        }
    }
    
    // setup current online clients
    var User = require('./models/user');
    app.use((req, res, next) => {
        res.locals.currentUser = req.user;
        res.locals.errors = req.flash('error');
        res.locals.infos = req.flash('info');
        next();
    });
    
    // callback from passport.socketio
    function onAuthorizeSuccess(data, accept) {
        console.log('🗲 Passport-Socket.IO conectado com sucesso');
    
        io.on('connection', function (socket) {
            console.log("🗲 Socket.IO-Native conectado com sucesso");
        });
    
        // get current user online after authentication
        io.on('connection', function (socket) {
    
            // get user details of documents in database
            app.get('/user-online', ensureAutheticated, (req, res) => {
                User.find()
                    .sort({ createdAd: 'descending' })
                    .exec((err, users) => {
                        if (err) return next(err);
                        // render response
                        res.send({
                            users: users
                        })
                    });
            });
        });
    
        accept();
    }
    
    function onAuthorizeFail(data, message, error, accept) {
        console.log('failed connection to socket.io:', data, message);
        if (error)
            accept(new Error(message));
    }
    

    使用者js公司

    var mongoose = require('mongoose');
    var bcrypt = require('bcrypt-nodejs');
    const SALT_FACTOR = 10;
    
    var userSchema = mongoose.Schema({
        username: { type: String, required: true, unique: true },
        password: { type: String, required: true },
        createdAt: { type: Date, default: Date.now },
        displayName: String,
        bio: String
    });
    
    userSchema.methods.name = function() { return this.displayName || this.username;}
    
    function noop() { };
    
    userSchema.pre('save', function(done) {
        var user = this;
        console.log('USER: ' + JSON.stringify( user));
    
        if (!( user.isModified('password'))) return done();
        bcrypt.genSalt(SALT_FACTOR, function(err, salt) {
            if (err) return done(err);
            bcrypt.hash(user.password, salt, noop,
               function (err, hashedPassword)  {
                    if (err) return done(err);
                    user.password = hashedPassword;
                    done();
                });
        });
    });
    
    userSchema.methods.checkPassword = function(guess, done){
        bcrypt.compare(guess, this.password, function(err, isMatch){
            done(err,isMatch);
        });
    };
    
    var User = mongoose.model('User', userSchema);
    
    module.exports = User;
    

    我在登录后尝试在集合中进行查询,以列出我登录的用户,但它仅限于1个用户,我没有选择更好地处理此结果,非常感谢他们给我的帮助!

    1 回复  |  直到 8 年前
        1
  •  7
  •   Rahul    8 年前

    您可以跟踪连接、断开连接、登录和注销事件,以创建联机用户列表。 您可以在RAM中管理在线用户,也可以使用redis进行管理。下面的代码片段可以帮助您实现目标-

    // Store userIds here
    let onlineUsers = [];
    
    io.on('connection', function (socket) {
    
        socket.on('login', (userTokenOrId) => {
            // store this to onlineUsers or redis
            // Other stuff
        });
        socket.on('logout', (userTokenOrId) => {
            // remove this from onlineUsers or redis
            // Other stuff
        });
        socket.on('disconnect', (userTokenOrId) => {
            // remove this from onlineUsers or redis
            // Other stuff
        });
    });
    

    为了更好地使用,您可以管理一个对象数组来存储同一个对象的userId和socketId列表,并管理一个对象来将socketId映射到userId。通过这种方式,您可以跟踪一个用户在不同的浏览器/系统上在线的情况。

    推荐文章