如何在 Node.js 中从请求参数获取经过身份验证的用户到 socket.io
Posted
技术标签:
【中文标题】如何在 Node.js 中从请求参数获取经过身份验证的用户到 socket.io【英文标题】:How to get authenticated user from request param to socket.io in Node.js 【发布时间】:2021-10-28 21:22:20 【问题描述】:几天来,我一直试图弄清楚如何获取当前用户,以便将其传递给 socket.io 发射,但无济于事。我正在使用 Passport.js 进行身份验证、ejs、socket.io、express、mysql 和 node.js。下面是我的代码。
app.js
const path = require('path');
const express = require("express");
const cookieParser = require('cookie-parser');
const toastr = require('express-toastr');
const cors = require("cors");
const app = express();
const httpServer = require("http").createServer(app);
const io = require("socket.io")(httpServer);
const fileUpload = require('express-fileupload');
const flash = require('connect-flash');
const session = require('express-session');
const passport = require('passport');
const moment = require('moment');
require('dotenv').config();
// Set configuration
app.use(express.urlencoded( extended: true ));
app.use(express.static(path.join(__dirname, 'assets')));
app.use(express.static(path.join(__dirname + '/public')));
app.use(express.static(path.join(__dirname + '/libs')));
app.use(cookieParser(process.env.SECRET_KEY));
app.use(session(
secret : process.env.SECRET_KEY,
saveUninitialized : true,
resave : true
));
app.use(flash());
app.use(toastr());
app.use(cors());
app.use(fileUpload(
createParentPath: true
));
require('./config/passport')(passport);
app.use(passport.initialize());
app.use(passport.session());
app.use((req, res, next) =>
res.locals.errors = req.flash('errors');
res.locals.error = req.flash('error');
res.locals.success = req.flash('success');
res.locals.values = req.flash('values');
res.locals.toastr = req.flash('toastr');
res.locals.moment = moment;
next();
);
app.set('view engine', 'ejs');
app.set('views', 'views');
// Local files
const adminRoutes = require('./routes/admin');
const userRoutes = require('./routes/user');
const translatorRoutes = require('./routes/translator');
const authRoutes = require('./routes/auth');
const indexRoutes = require('./routes/index');
const ensureAuthenticated = require('./config/authMiddleware');
const User = require('./app/models/user');
io.on("connection", socket =>
console.log('Socket 1 is connected -- ' + socket.id);
// socket.on('get-authenticated-user', data =>
// console.log(data);
// );
socket.on('current-user', (data) => console.log(data));
socket.on('disconnect', () =>
console.log('User disconnected');
);
);
// Routes
app.get('/', ensureAuthenticated, indexRoutes);
app.use('/admin', ensureAuthenticated, adminRoutes);
app.use('/admin', ensureAuthenticated, translatorRoutes);
app.use('/admin', ensureAuthenticated, userRoutes);
// app.get('/users', (req, res) =>
// const model = new User();
// model.all([], (err, rows) =>
// return res.json(rows);
// );
// );
app.use(indexRoutes);
// app.use('/admin', adminRoutes);
// app.use('/admin', translatorRoutes);
// app.use('/admin', userRoutes);
app.use(authRoutes);
// 404 Page
app.use((req, res) =>
res.render('404', pageTitle: '404 Page not found' );
);
httpServer.listen(process.env.PORT);
index.js(路由器)
const express = require('express');
const router = express.Router();
const getCurrentUser = require('../config/functions');
const io = require('socket.io');
const socket = io('/');
router.get('/', (req, res) =>
socket.emit('get-current-user', req.user);
res.render('welcome', pageTitle: 'Welcome!', isLogin: false, user: req.user );
);
module.exports = router;
用于身份验证的passport.js
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
const db = require('../app/database/database');
const moment = require('moment');
const io = require('socket.io');
module.exports = (passport) =>
passport.use(new LocalStrategy( usernameField: 'email' , (email, password, done) =>
db.query('SELECT * FROM users WHERE email = ?', [email], (err, rows, fields) =>
if (err) throw err;
if (rows.length <= 0)
return done(null, false, message: 'Email incorrect' );
const user = rows[0];
bcrypt.compare(password, user.passwd, (errm, isMatch) =>
if (errm) throw errm;
if (isMatch)
// io.emit('get-current-user', user);
const sql = `UPDATE users SET last_logged_in = ? WHERE email = ?`;
db.query(sql, [moment().format(), email], (_, __) =>
return done(null, user);
);
else
return done(null, false, message: 'Password incorrect' );
);
);
));
passport.serializeUser((user, done) =>
done(null, user);
);
passport.deserializeUser((user, done) =>
db.query('SELECT * FROM users WHERE id = ?', [user.id], (err, rows, fields) =>
if (err) throw err;
if (rows.length <= 0)
return done(null, false, message: 'Record is not found in our database' );
const setUser = rows[0];
done(err, setUser);
);
);
;
main.js
// Initialization of Socket.io Connection
const socket = io("/");
let user;
function userInfo(u)
user = u;
// wss.registerSocketEvents(socket);
socket.on('connect', () =>
console.log('connecting from client');
// Test if emitting user is working
socket.emit('current-user',
name: 'Woo Bear',
email: "woo@live.com",
socketId: socket.id,
);
registerSocketEvents(socket);
);
const getUser = (user) =>
console.log(user);
;
// webRTCHandler.getLocalPreview();
// // Copy Personal Code - Add Event Listener - Click
// const personalCodeCopyButton = document.getElementById('personal_code_copy_button');
// personalCodeCopyButton.addEventListener('click', () =>
// const personalCode = store.getState().socketId;
// navigator.clipboard && navigator.clipboard.writeText(personalCode);
// );
// // Add Event Listener - Chat and Video click
// const personalCodeChatButton = document.getElementById('personal_code_chat_button');
// const personalCodeVideoButton = document.getElementById('personal_code_video_button');
// personalCodeChatButton.addEventListener('click', () =>
// console.log('chat click');
// const personalCodeInput = document.getElementById('personal_code_input').value;
// webRTCHandler.sendPreOffer(constants.callType.CHAT_PERSONAL_CODE, personalCodeInput);
// );
// personalCodeVideoButton.addEventListener('click', () =>
// console.log('video click');
// const personalCodeInput = document.getElementById('personal_code_input').value;
// webRTCHandler.sendPreOffer(constants.callType.VIDEO_PERSONAL_CODE, personalCodeInput);
// );
// // event listeners for video call buttons
// const micButton = document.getElementById('mic_button');
// micButton.addEventListener('click', () =>
// const localStream = store.getState().locatStream;
// const micEnabled = localStream.getAudioTracks()[0].enabled;
// localStream.getAudioTracks()[0].enabled = !micEnabled;
// ui.updateMicButton(micEnabled);
// console.log(localStream.getAudioTracks()[0]);
// );
// const cameraButton = document.getElementById('camera_button');
// cameraButton.addEventListener('click', () =>
// const localStream = store.getState().locatStream;
// const cameraEnabled = localStream.getVideoTracks()[0].enabled;
// localStream.getVideoTracks()[0].enabled = !cameraEnabled;
// ui.updateCameraButton(cameraEnabled);
// );
// const switchForScreenSharingButton = document.getElementById('screen_sharing_button');
// switchForScreenSharingButton.addEventListener('click', () =>
// const screenSharingActive = store.getState().screenSharingActive;
// webRTCHandler.switchBetweenCameraAndScreenSharing(screenSharingActive);
// );
// const newMessageInput = document.getElementById('new_message_input');
// newMessageInput.addEventListener('keydown', (event) =>
// console.log('User types');
// const key = event.key;
// if (key === 'Enter')
// webRTCHandler.sendMessageUsingDataChannel(event.target.value);
// ui.appendMessage(event.target.value, true);
// newMessageInput.value = '';
//
// );
// const sendMessageButton = document.getElementById('send_message_button');
// sendMessageButton.addEventListener('click', () =>
// webRTCHandler.sendMessageUsingDataChannel(newMessageInput.value);
// ui.appendMessage(newMessageInput.value, true);
// newMessageInput.value = '';
// );
welcome.ejs
<%- include('includes/head.ejs') %>
<link rel="stylesheet" href="/css/video.css">
</head>
<body class="layout-top-nav" style="height: auto;">
<div class="wrapper">
<!-- Navbar -->
<div class="display-none">
<nav class="main-header navbar navbar-expand-md navbar-dark navbar-primary">
<div class="container">
<a href="/" class="navbar-brand">
<i class="text-white fa fa-desktop" aria-hidden="true"></i>
<span class="brand-text font-weight-light">GSL Translators</span>
</a>
<ul class="order-1 ml-auto order-md-3 navbar-nav navbar-no-expand">
<li class="nav-item dropdown">
<a class="nav-link" data-toggle="dropdown" href="#">
More
<i class="fas fa-caret-down"></i>
</a>
<div class="dropdown-menu dropdown-menu-lg dropdown-menu-right">
<div class="dropdown-divider"></div>
<a href="/admin/profile" class="dropdown-item">
<i class="mr-2 fas fa-phone"></i> Contact
</a>
<div class="dropdown-divider"></div>
<a href="#" class="dropdown-item">
<i class="mr-2 fas fa-info"></i> About
</a>
<div class="dropdown-divider"></div>
<a href="/logout" class="dropdown-item">
<i class="mr-2 fas fa-power-off" aria-hidden="true"></i></i> Log out
</a>
</li>
</ul>
</div>
</nav>
<!-- /.navbar -->
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper" style="min-height: 520.5px;">
<!-- Content Header (Page header) -->
<div class="content-header">
<div class="container">
</div><!-- /.container-fluid -->
</div>
<!-- /.content-header -->
<!-- Main content -->
<div class="content">
<div class="container px-2">
<div class="row">
<% for (let i=0; i < 4; i++) %>
<div class="col-md-3 col-sm-4 col-sm">
<div class="card card-primary r-5 elevation-3">
<div class="p-0 card-body box-profile">
<div class="text-center">
<!-- <img class="profile-user-img img-fluid img-circle" src="img/user4-128x128.jpg"
> -->
<img src="img/user4-128x128.jpg" class="rt-5"
style="width: 100%; max-height: 13rem;">
</div>
<div class="p-2 mb-2">
<h3 class="text-center profile-username">Cyril Eduafo</h3>
<p class="mb-1 text-center text-muted">0501395590</p>
<p class="mb-1 text-center text-muted">Available</p>
<p class="mb-1 text-center text-muted">
<i class="text-orange fa fa-star" aria-hidden="true"></i>
<i class="text-orange fa fa-star" aria-hidden="true"></i>
<i class="text-orange fa fa-star" aria-hidden="true"></i>
<i class="text-orange fa fa-star" aria-hidden="true"></i>
</p>
<div class="mt-2 text-center">
<button class="py-1 rounded btn-call bg-success w-25">
<i class="fa fa-video" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<!-- /.card-body -->
</div>
</div>
<% %>
</div>
<!-- /.row -->
</div><!-- /.container-fluid -->
</div>
<!-- /.content -->
</div>
</div>
<div id="hidden dialog"></div>
<%- include('includes/footer.ejs') %>
<script src="/socket.io/socket.io.js"></script>
<!-- jQuery -->
<script src="/js/jquery.min.js"></script>
<!-- Bootstrap 4 -->
<script src="/js/bootstrap.bundle.js"></script>
<!-- AdminLTE App -->
<script src="/js/adminlte.min.js"></script>
<script src="/js/sweetalert2.min.js"></script>
<script src="/js/toastr.min.js"></script>
<script src="/js/ui-store.min.js"></script>
<script src='store.js'></script>
<!-- <script src='elements.js'></script>
<script src='constants.js'></script>
<script src='ui.js'></script> -->
<script src='wss.js'></script>
<!-- <script src='webRTCHandler.js'></script> -->
<script src="main.js"></script>
<script>
// Get user
userInfo(<%= user %>);
</script>
<%- typeof toastr != undefined ? toastr : ""%>
</body>
</html>
package.json
"name": "gsl_translators",
"version": "1.0.0",
"description": "This is for Toah's project work for his MSc ICT",
"main": "app.js",
"scripts":
"start": "nodemon app.js"
,
"repository":
"type": "git",
"url": "git+https://github.com/ljsharp/gsl_translators.git"
,
"author": "Leslie Joe - LJ Sharp",
"license": "ISC",
"bugs":
"url": "https://github.com/ljsharp/gsl_translators/issues"
,
"homepage": "https://github.com/ljsharp/gsl_translators#readme",
"dependencies":
"@fabrice8/ui-store": "^1.0.5",
"bcrypt": "^5.0.1",
"connect-flash": "^0.1.1",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"ejs": "^3.1.6",
"express": "^4.17.1",
"express-fileupload": "^1.2.1",
"express-session": "^1.17.2",
"express-toastr": "^2.0.2",
"express-validator": "^6.12.1",
"moment": "^2.29.1",
"mysql": "^2.18.1",
"nodemon": "^2.0.12",
"passport": "^0.4.1",
"passport-local": "^1.0.0",
"socket.io": "^4.1.3",
"storage-manager-js": "^4.0.6",
"uuidv4": "^6.2.12",
"validator": "^13.6.0"
我需要您的帮助来弄清楚我可以使用什么方法或技巧来获取当前或登录的用户。提前致谢。
【问题讨论】:
请看这个答案***.com/a/36821359/8201020 您可以使用相同的算法和密码来验证令牌。 【参考方案1】:解决了!!我找到了这篇文章 - Sharing Passport.Js Sessions With Both Express And Socket.Io 我现在可以获得经过身份验证的用户数据。让我放弃修复获取用户信息问题的代码。
添加以下包
const session = require('express-session');
const sessionStore = new session.MemoryStore();
const passportSocketIo = require('passport.socketio');
const passport = require('passport');
app.use(session(
secret : process.env.SECRET_KEY,
saveUninitialized : true,
resave : true,
key: 'express.sid',
store: sessionStore
));
io.use(passportSocketIo.authorize(
store: sessionStore,
key: 'express.sid',
passport: passport,
cookieParser: cookieParser,
secret: process.env.SECRET_KEY
));
let connectedUsers = [];
io.on("connection", socket =>
connectedUsers.push(
...socket.request.user,
socketId: socket.id,
);
console.log(connectedUsers);
// socket.on('current-user', (data) =>
// const connectedUser =
// ...data,
// socketId: socket.id,
// ;
// connectedUsers.push(connectedUser);
// console.log(connectedUsers);
// socket.emit('updatedUserLists', connectedUsers);
// );
socket.on('disconnect', () =>
console.log(socket.id);
connectedUsers = connectedUsers.filter(function(u)
console.log(u);
return u.socketId !== socket.id;
);
console.log(connectedUsers);
);
);
希望这对其他人有所帮助。祝你有美好的一天!
【讨论】:
以上是关于如何在 Node.js 中从请求参数获取经过身份验证的用户到 socket.io的主要内容,如果未能解决你的问题,请参考以下文章
如何检查用户是不是在 Firebase 和 Express/Node.js 中经过身份验证?
在 Flutter 的下拉列表中从 Firebase 获取经过身份验证的用户列表
Node.js JWT,从 token 中获取 user_id
每次在 Node.js (Express.js) 中发出 API 请求之前,如何简化 Fetching Auth token?