【问题标题】:Passport.SocketIo - How to get a list of online users with NodeJS, Express and PassportPassport.SocketIo - 如何使用 NodeJS、Express 和 Passport 获取在线用户列表
【发布时间】:2018-07-26 10:48:34
【问题描述】:

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

app.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));
}

user.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 个用户,我无法更好地处理此结果,非常感谢他们给我的帮助!

【问题讨论】:

标签: node.js express socket.io passport.js


【解决方案1】:

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

// 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 和相同的 socketIds 列表,以及一个对象来将 socketId 映射到 userId。通过这种方式,您可以跟踪一个用户在不同的浏览器/系统上在线。

【讨论】:

    猜你喜欢
    • 2017-11-02
    • 2015-03-24
    • 2021-05-14
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    相关资源
    最近更新 更多