У меня возникает проблема с Redis и ExpressJS.
Иногда пользователи отключаются от приложения, в моем приложении пользователь подключается с помощью passport
и passport-local
. Проблема возникает, когда пользователь перенаправляется на страницу, используя response.redirect()
.
. В настоящее время я думаю, что у меня возникают проблемы с экземплярами, возможно, пользователь перенаправляется на другой экземпляр, но я не знаю, как его использовать. липкие сеансы с redis.
My server.js
:
var express = require('express'),
engine = require('ejs-locals'),
path = require('path'),
redis = require('redis'),
session = require('express-session'),
RedisStore = require('connect-redis')(session),
redisClient = redis.createClient(),
compression = require('compression'),
dotenv = require('dotenv'),
_ = require('lodash'),
fs = require('fs-extra'),
colors = require('colors'),
passport = require('passport'),
flash = require('connect-flash'),
models = require('./app/models/0-Index'),
logMiddleware = require('./middlewares/log'),
breadcrumbMiddleware = require('./middlewares/breadcrumb'),
errorMiddleware = require('./middlewares/error'),
localVariablesMiddleware = require('./middlewares/localVariables'),
localFunctionsMiddleware = require('./middlewares/localFunctions'),
localShortcodesMiddleware = require('./middlewares/localShortcodes'),
securityMiddleware = require('./middlewares/security'),
metadatasFilter = require('./app/filters/metadatasFilter'),
server = Object.create(null);
server.init = init;
function init(options) {
var controllerFilePath,
view = this;
this.port = options && options.port || 3000;
this.pathRoot = __dirname;
this.pathControllers = path.join(this.pathRoot, 'app', 'controllers');
this.pathApplicationModules = path.join(this.pathRoot, 'extendedapp');
this.app = express();
setDefaultParams.call(this);
logMiddleware(this);
localVariablesMiddleware(this);
localFunctionsMiddleware(this);
localShortcodesMiddleware(this);
securityMiddleware(this);
breadcrumbMiddleware(this);
this.app.locals.modifyingIndexView = [];
// Chargement des contrôleurs du projet
_.forEach(fs.readdirSync(this.pathControllers), function(controller) {
controllerFilePath = path.join(view.pathControllers, controller);
controller = require(controllerFilePath);
addRoutes.call(view, controller);
console.log(colors.blue('Loading module : ' + controllerFilePath.replace(view.pathControllers + '\\', '')));
});
// chargement des contrôleurs des applications complémentaires
_.forEach(fs.readdirSync(this.pathApplicationModules), function(module) {
if (module !== '.gitignore') {
var extendedApps = JSON.parse(fs.readFileSync('./configs/options.json', 'utf8')).extendedApps,
extendedApp = _.find(extendedApps, { name: module });
if (extendedApp.state) {
_.forEach(fs.readdirSync(path.join(view.pathApplicationModules, module, 'controllers')), function(controller) {
if (controller !== '.gitignore') {
controllerFilePath = path.join(path.join(view.pathApplicationModules, module, 'controllers'), controller);
controller = require(controllerFilePath);
addRoutes.call(view, controller);
console.log(colors.blue('Loading extended app : ' + controllerFilePath.replace(path.join(view.pathApplicationModules, module, 'controllers') + '\\', '')));
}
});
}
}
});
errorMiddleware(this);
// Chargement du serveur
models.sequelize.sync().then(function() {
run.call(view);
process.on('SIGINT', function() {
models.sequelize.connectionManager.close();
process.exit(1);
});
});
controller = controllerFilePath = null;
}
function setDefaultParams() {
this.app.engine('ejs', engine);
this.app.set('views', path.join(this.pathRoot, 'app', 'views'));
this.app.set('view engine', 'ejs');
this.app.locals._layoutFile = true;
this.app.locals.breadcrumb = [];
this.app.use(express.static(path.join(this.pathRoot, 'public')));
this.app.set('trust proxy', 1);
this.app.use(flash());
// this.app.use(session({
// secret: 'gesti15aweb',
// // name : 'sessionId',
// // proxy: true,
// resave: true,
// saveUninitialized: true
// }));
this.app.use(
session({
store: new RedisStore({ client: redisClient }),
secret: 'gesti15aweb',
resave: false,
saveUninitialized: true
})
);
this.app.use(compression());
this.app.use(passport.initialize());
this.app.use(passport.session());
dotenv.config();
}
function run() {
var view = this;
this.app.listen(view.port, function() {
console.log(colors.yellow('Gestiaweb is running on port ' + view.port));
});
}
function addRoutes(controller) {
var view = this;
_.forEach(controller.getRoutes, function(route, index) {
if (index === '/_index') {
view.app.locals.modifyingIndexView.push(controller.baseUrl.substring(1));
}
view.app.get(
((route.noBaseUrl) ? '' : controller.baseUrl) + index,
[].concat(metadatasFilter, route.filters || []),
route.action.bind(controller)
);
});
_.forEach(controller.postRoutes, function(route, index) {
view.app.post(
((route.noBaseUrl) ? '' : controller.baseUrl) + index,
[].concat(metadatasFilter, route.filters || []),
route.action.bind(controller)
);
});
}
module.exports = server;
и UserController.js
:
var passport = require('../../middlewares/localStrategy'),
bcrypt = require('bcryptjs'),
moment = require('moment'),
_ = require('lodash'),
sequelize = require('../models/0-Index').sequelize,
sendMailHelper = require('../helpers/SendMailHelper'),
RootController = require('./0-RootController'),
authorizeFront = require('../filters/authorizeFront'),
models = require('../models/0-Index'),
generator = require('generate-password'),
Recaptcha = require('express-recaptcha').RecaptchaV2,
options = require('../../configs/options'),
recaptchaparam = _.find(options.blocks, { name: 'recaptchaparam' }),
siteKey = recaptchaparam.params[0].value,
secretKey = recaptchaparam.params[1].value,
recaptcha = (siteKey && secretKey) && new Recaptcha(siteKey, secretKey),
UserModel = models.UserModel,
UserController = Object.create(RootController);
UserController.baseUrl = '/user';
UserController.getRoutes = {
'/signin': { action: signin },
'/passwordreset': { action: passwordreset },
'/add': { action: add, filters: [recaptcha.middleware.render] },
'/__show': { action: __show, filters: [authorizeFront] },
'/_signin': { action: _signin },
'/signout': { action: signout, filters: [recaptcha.middleware.render] }
};
UserController.postRoutes = {
'/signin': { action: postSignin, filters: [passport.authenticate('gestiaweb-local', { failureRedirect: '/user/signin', failureFlash: true })] },
'/add': { action: postAdd, filters: [recaptcha.middleware.verify] },
'/_signin': { action: _postSignin, filters: [passport.authenticate('gestiaweb-local', { failureRedirect: '/user/_signin', failureFlash: true })] },
'/passwordreset': { action: postPasswordreset, filters: [recaptcha.middleware.verify] }
};
/* --------------- GET FUNCTION --------------- */
function signin(request, response) {
response.render('user/signin', {
returnurl: request.query.returnurl || '/user/show',
page: {
seo_title: 'Connexion',
title: 'Connexion',
content: ''
}
});
}
function add(request, response) {
response.render('user/add', {
returnurl: request.query.returnurl,
recaptcha: response.recaptcha,
page: {
seo_title: 'Inscription',
title: 'Inscription',
content: ''
}
});
}
function __show(request, response) {
response.render('user/__show', {
page: {
seo_title: 'Mon profil',
title: 'Mon profil',
content: ''
}
});
}
function _signin(request, response) {
var flash = request.flash();
if (flash && flash.error) {
request.flash('danger', flash.error[0]);
return response.redirect(this.baseUrl + '/_signin');
}
response.render('user/_signin', {
returnurl: request.query.returnurl || '/glovebox',
_layoutFile: false
});
}
function signout(request, response) {
request.logout();
response.redirect(this.rootUrl);
}
function passwordreset(request, response) {
response.render('user/passwordreset', {
page: {
seo_title: 'Réinitialisation du mot de passe',
title: 'Réinitialisation du mot de passe',
content: ''
},
recaptcha: response.recaptcha
});
}
/* --------------- /GET FUNCTION -------------- */
/* --------------- POST FUNCTION --------------- */
function postSignin(request, response) {
request.flash('success', 'Connexion réussi');
response.redirect(request.body.returnurl);
}
function _postSignin(request, response) {
request.flash('success', 'Connexion réussi');
response.redirect(request.body.returnurl);
}
function postAdd(request, response) {
var view = this,
user = request.body.user;
user.birth = (user.birth) ? moment(user.birth, 'YYYY-MM-DD').format('YYYY-MM-DD 00:00:00') : null;
if (!request.recaptcha.error) {
bcrypt.hash(user.password, 10, function(err, hash) {
user.password = hash;
sequelize.query('select * from user where username = \'' + user.username + '\' or email = \'' + user.email + '\'').spread(function(results) {
if (results && results.length) {
request.flash('success', 'Il existe déjà un utilisateur avec cet e-mail ou ce mot de passe');
response.redirect(request.body.returnurl || view.baseUrl + '/add');
} else {
UserModel.create(user).then(function(createdUser) {
var subject = "Bienvenue " + createdUser.username + ",";
var content = "Nous vous confirmons la création de votre compte sur " + response.locals.websiteUrl + ".";
sendMailHelper.send(response.locals.blocks.contactparam.email, createdUser.email, subject, content, null, null, 1329482, response.locals).then( function() {
request.flash('success', 'Nous avons bien pris en compte votre inscription');
response.redirect(request.body.returnurl || '/user/signin');
}).catch( function(err) {
console.log(err);
});
});
}
});
});
} else {
request.flash('danger', 'Erreur avec le Captcha');
response.redirect(request.body.returnurl || view.baseUrl + '/signin');
}
}
function postPasswordreset(request, response) {
var view = this,
user = request.body.user,
hashedPassword,
generatedPassword = generator.generate({
length: 10,
numbers: true
});
if (!request.recaptcha.error) {
UserModel.findOne({ where: { email: user.email } }).then(function(userFinded) {
if (userFinded) {
bcrypt.hash(generatedPassword, 10, function(err, hash) {
hashedPassword = hash;
userFinded.update({ password: hashedPassword }).then(function() {
var htmlMessage,
to = userFinded.email;
htmlMessage = '<p>Votre identifiant : ' + userFinded.username + '</p><p>Votre nouveau mot de passe : ' + generatedPassword + '</p>';
sendMailHelper.send(response.locals.blocks.contactparam.email, to, 'Réinitialisation de votre mot de passe', htmlMessage, null, null);
request.flash('success', 'Nous avons réinitialisé votre mot de passe. Merci de consulter votre messagerie.');
response.redirect(view.baseUrl + '/signin');
});
});
} else {
request.flash('danger', 'Nous n\'avons pas trouvé d\'utilisateur avec ce nom utilisateur ou cet e-mail');
response.redirect(view.baseUrl + '/passwordreset');
}
});
} else {
request.flash('danger', 'Erreur avec le Captcha');
return response.redirect(view.baseUrl + '/passwordreset');
}
}
/* --------------- /POST FUNCTION --------------- */
module.exports = UserController;
Я использую PM2 в режиме кластера для запуска моего приложение.