我遇到了会话问题,护照成功后获取 req.user 未定义。验证方法。
基本上在注册或登录后,当我重定向时,无法在请求变量中找到“用户”。
我使用了一个使用mongo的黑客马拉松启动器,我试图将其更改为使用Postgres。
编辑-按照“评论”的建议
现在注册流程运行良好,但是登录流程存在一些问题。当我添加许多断点时,发生了一些奇怪的事情,它似乎间歇性地登录。使用注释建议更新代码
app.js
const express = require('express');
const compression = require('compression');
const session = require('express-session');
const bodyParser = require('body-parser');
const logger = require('morgan');
const chalk = require('chalk');
const errorHandler = require('errorhandler');
const lusca = require('lusca');
const dotenv = require('dotenv');
const flash = require('express-flash');
const path = require('path');
const passport = require('passport');
const expressValidator = require('express-validator');
const expressStatusMonitor = require('express-status-monitor');
const sass = require('node-sass-middleware');
const multer = require('multer');
dotenv.load({ path: '.env.example' });
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const models = require('./models');
const upload = multer({ dest: path.join(__dirname, 'uploads') });
/**
* Load environment variables from .env file, where API keys and passwords are configured.
*/
/**
* Controllers (route handlers).
*/
const homeController = require('./controllers/home');
const userController = require('./controllers/user');
const contactController = require('./controllers/contact');
const dashController = require('./controllers/dash');
const currencyController = require('./controllers/currency');
const accountController = require('./controllers/account');
const testController = require('./controllers/test');
const txController = require('./controllers/transaction');
/**
* API keys and Passport configuration.
*/
const passportConfig = require('./config/passport');
/**
* Create Express server.
*/
const app = express();
/**
* Express configuration.
*/
app.set('host', '127.0.0.1');
app.set('port', 8080);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(expressStatusMonitor());
app.use(compression());
app.use(sass({
src: path.join(__dirname, 'public'),
dest: path.join(__dirname, 'public')
}));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(session({
resave: true,
saveUninitialized: true,
secret: process.env.SESSION_SECRET,
cookie: { maxAge: 1209600000 }, // two weeks in milliseconds
store: new SequelizeStore({
db: models.sequelize
})
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use((req, res, next) => {
// if (req.path === '/api/upload') {
// next();
// } else {
// lusca.csrf()(req, res, next);
// }
next();
});
app.use(lusca.xframe('SAMEORIGIN'));
app.use(lusca.xssProtection(true));
app.disable('x-powered-by');
app.use((req, res, next) => {
res.locals.user = req.user;
next();
});
app.use((req, res, next) => {
// After successful login, redirect back to the intended page
if (!req.user
&& req.path !== '/login'
&& req.path !== '/signup'
&& !req.path.match(/^\/auth/)
&& !req.path.match(/\./)) {
req.session.returnTo = req.originalUrl;
} else if (req.user
&& (req.path === '/account' || req.path.match(/^\/api/))) {
req.session.returnTo = req.originalUrl;
}
next();
});
app.use('/', express.static(path.join(__dirname, 'public'), { maxAge: 31557600000 }));
app.use('/js/lib', express.static(path.join(__dirname, 'node_modules/chart.js/dist'), { maxAge: 31557600000 }));
app.use('/js/lib', express.static(path.join(__dirname, 'node_modules/popper.js/dist/umd'), { maxAge: 31557600000 }));
app.use('/js/lib', express.static(path.join(__dirname, 'node_modules/bootstrap/dist/js'), { maxAge: 31557600000 }));
app.use('/js/lib', express.static(path.join(__dirname, 'node_modules/jquery/dist'), { maxAge: 31557600000 }));
app.use('/webfonts', express.static(path.join(__dirname, 'node_modules/@fortawesome/fontawesome-free/webfonts'), { maxAge: 31557600000 }));
/**
* Primary app routes.
*/
app.get('/', homeController.index);
app.get('/login', userController.getLogin);
app.post('/login', userController.postLogin);
app.get('/logout', userController.logout);
app.get('/forgot', userController.getForgot);
app.post('/forgot', userController.postForgot);
app.get('/reset/:token', userController.getReset);
app.post('/reset/:token', userController.postReset);
app.get('/signup', userController.getSignup);
app.post('/signup', userController.postSignup);
// app.get('/account', passportConfig.isAuthenticated, userController.getAccount);
// app.post('/account/profile', passportConfig.isAuthenticated, userController.postUpdateProfile);
app.post('/account/password', passportConfig.isAuthenticated, userController.postUpdatePassword);
// app.post('/account/delete', passportConfig.isAuthenticated, userController.postDeleteAccount);
// app.get('/account/unlink/:provider', passportConfig.isAuthenticated, userController.getOauthUnlink);
app.get('/dashboard', passportConfig.isAuthenticated, dashController.index);
app.get('/test', passportConfig.isAuthenticated, testController.test);
// app.get('/contact', contactController.contact);
// app.post('/addContact', contactController.addContact);
// app.post('/editContact', contactController.editContact);
// app.get('/listContacts', contactController.listContacts);
// app.get('/listCurrency', currencyController.listCurrency);
// app.post('/addAccount', accountController.addAccount);
// app.post('/editAccount', accountController.editAccount);
// app.get('/listAccounts', accountController.listAccounts);
// app.get('/getTransactions', txController.getTransactions);
/**
* Error Handler.
*/
if (process.env.NODE_ENV === 'development') {
// only use in development
app.use(errorHandler());
} else {
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send('Server Error');
});
}
/**
* Start Express server.
*/
models.sequelize.sync({}).then(() => {
app.listen(app.get('port'), () => {
console.log('%s App is running at http://localhost:%d in %s mode', chalk.green('✓'), app.get('port'), app.get('env'));
console.log('Press CTRL-C to stop\n');
});
});
module.exports = app;
user.js
const { promisify } = require('util');
const crypto = require('crypto');
const nodemailer = require('nodemailer');
const passport = require('passport');
const models = require('../models');
const { User } = models;
const randomBytesAsync = promisify(crypto.randomBytes);
/**
* GET /login
* Login page.
*/
exports.getLogin = (req, res) => {
if (req.user) {
return res.redirect('/');
}
res.render('account/login', {
title: 'Login'
});
};
/**
* POST /login
* Sign in using email and password.
*/
exports.postLogin = (req, res, next) => {
req.assert('email', 'Email is not valid').isEmail();
req.assert('password', 'Password cannot be blank').notEmpty();
req.sanitize('email').normalizeEmail({ gmail_remove_dots: false });
const errors = req.validationErrors();
if (errors) {
req.flash('errors', errors);
return res.redirect('/login');
}
passport.authenticate('local', (err, user, info) => {
if (err) { return next(err); }
if (!user) {
req.flash('errors', info);
return res.redirect('/login');
}
req.logIn(user, (err) => {
if (err) { return next(err); }
res.locals.user = user; //Updated code after comment suggestions
req.flash('success', { msg: 'Success! You are logged in.' });
res.redirect('/dashboard');
});
})(req, res, next);
};
/**
* GET /logout
* Log out.
*/
exports.logout = (req, res) => {
req.logout();
req.session.destroy((err) => {
if (err) console.log('Error : Failed to destroy the session during logout.', err);
req.user = null;
res.redirect('/');
});
};
/**
* GET /signup
* Signup page.
*/
exports.getSignup = (req, res) => {
if (req.user) {
return res.redirect('/');
}
res.render('account/signup', {
title: 'Create Account'
});
};
/**
* POST /signup
* Create a new local account.
*/
exports.postSignup = (req, res, next) => {
req.assert('email', 'Email is not valid').isEmail();
req.assert('password', 'Password must be at least 4 characters long').len(4);
req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password);
req.sanitize('email').normalizeEmail({ gmail_remove_dots: false });
const errors = req.validationErrors();
if (errors) {
req.flash('errors', errors);
return res.redirect('/signup');
}
User.findAll({ limit: 1, where: { email: req.body.email }, plain: true })
.then((existingUser) => {
if (existingUser) {
req.flash('errors', { msg: 'Account with that email address already exists.' });
return res.redirect('/signup');
}
User.create({
email: req.body.email,
password: req.body.password
}).then((user) => {
req.logIn(user, (err) => {
if (err) { return next(err); }
res.locals.user = user; //updated code after comment suggestions
return res.redirect('/');
});
}).catch(error => next(error));
});
};
passport.js
const passport = require('passport');
const request = require('request');
const { Strategy: LocalStrategy } = require('passport-local');
const _ = require('lodash');
const models = require('../models');
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
models.User.findAll({ where: { id }, limit: 1, plain: true })
.then(user => done(null, user))
.catch(err => done(err));
});
/**
* Sign in using Email and Password.
*/
passport.use(new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
models.User.findAll({ where: { email }, limit: 1, plain: true }).then((user) => {
if (!user) {
return done(null, false, { msg: `Email ${email} not found.` });
}
user.comparePassword(password, (err, isMatch) => {
if (err) { return done(err); }
if (isMatch) {
return done(null, user);
}
return done(null, false, { msg: 'Invalid email or password.' });
});
}).catch(error => done(error));
}));
/**
* OAuth Strategy Overview
*
* - User is already logged in.
* - Check if there is an existing account with a provider id.
* - If there is, return an error message. (Account merging not supported)
* - Else link new OAuth account with currently logged-in user.
* - User is not logged in.
* - Check if it's a returning user.
* - If returning user, sign in and we are done.
* - Else check if there is an existing account with user's email.
* - If there is, return an error message.
* - Else create a new account.
*/
/**
* Login Required middleware.
*/
exports.isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/login');
};
/**
* Authorization Required middleware.
*/
exports.isAuthorized = (req, res, next) => {
const provider = req.path.split('/').slice(-1)[0];
const token = req.user.tokens.find(token => token.kind === provider);
if (token) {
next();
} else {
res.redirect(`/auth/${provider}`);
}
};
答案 0 :(得分:0)
是否可以共享在password.js LocalStrategy中引用此代码的用户对象示例
user.comparePassword(password, (err, isMatch) => {....});
看起来user.id在serializeuser中不可用,这可能是它无法在会话中设置user.id并无法反序列化User的原因,进一步导致用户未在req中设置用户对象
passport.serializeUser((user, done) => {
done(null, user.id);
});
答案 1 :(得分:0)
在app.js
中,您需要在初始化const passportConfig = require('./config/passport');
之后调用passport
,如下所示:
app.use(passport.initialize());
app.use(passport.session());
// place it here
const passportConfig = require('./config/passport')(passport);
此外,您需要调整密码配置文件(./config/passport
),以便在模块加载时可以获得实例化的passport
实例。 app.js
,然后使用它而不是通过passport
加载新的require('passport')
实例-我认为这使事情变得混乱了;虽然没有测试。 :)