刚开始使用PassportJS,到目前为止可以有一个用户登录,根据用户角色限制页面等等。但我注意到的一件事是,我可以使用相同的凭据通过多个设备登录。这是我关心的,因为同样的登录可以共享,这不是我想要的。
我的问题是我怎样才能阻止这一切?我目前的设置只是一个运行在单个实例上的express应用程序(目前还没有达到不需要的跨多个实例的负载平衡,当我这样做时,我知道我可以使用redis来存储会话详细信息并从那里开始)。但现在我想知道是否有一种方法可以用当前设置的Passport来实现这一点
我省略了我觉得不必要的部分,以免把问题夸大了
# server.js
const session = require('express-session');
const passport = require('passport');
require('./config/passport')(passport); // pass passport for configuration
// Init App
const app = express();
// BodyParser Middleware
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json()); // get information from html forms
app.use(session({
secret: 'cookie_secret',
name: 'cookie_name',
resave: true,
saveUninitialized: true,
cookie: { maxAge: 5400000 },
}));
app.use(passport.initialize());
app.use(passport.session());
// routes
require('./routes/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
const port = process.env.PORT || 4000;
app.listen(port, () => {
console.log('listening on port ' + port);
});
护照配置
# config/passport.js
const bcrypt = require('bcryptjs'); // hash password
const LocalStrategy = require('passport-local').Strategy;
const pool = require('./database.js'); // database Connection
const User = require('../models/user'); // load up the user model
module.exports = (passport) => {
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
},
(req, email, password, done) => {
pool.query('SELECT * from users where email=$1', [email], (err, result) => {
if (err) return done(null, false, { message: 'Incorrect Email or Password' });
if (result.rows.length > 0) {
const user = result.rows[0];
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch === true) { return done(null, user);
}
return done(null, false, { message: 'Incorrect Email or Password'
});
}); // bcrypt
} else {
return done(null, false, { message: 'Incorrect Email or Password' });
}
});
}));
};
当用户登录时,他们会执行本地登录策略,我有方法检查用户是否可以访问试图访问的页面
const checkAuthentication = require('../helpers/auth');
// Members Page
app.get('/members', checkAuthentication, async (req, res) => {
res.render('members');
});
app.post('/login', passport.authenticate('local-login', {
successRedirect: '/members',
failureRedirect: '/',
failureFlash: true,
}));
# auth.js
module.exports = (req, res, next) => {
if (req.isAuthenticated()) {
if (new Date(req.user.membership_expiry_date) < new Date()) { // if expiry date < todays date
req.flash('error', 'Membership Expired');
return res.redirect('/');
}
} else {
return res.redirect('/');
}
return next();
};
我希望那里有足够的信息,概括地说,我希望一次只允许一个用户登录一个会话,所以一次一个设备,没有多个登录
谢谢