Вопрос или проблема
app.js
const express = require('express');
const chalk = require('chalk');
const app = express();
const debug = require('debug')('app')
const path = require('path');
const morgan = require('morgan');
const passport = require('passport');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const sessionRouter = require('./src/routers/routerSession');
const adminRouter = require('./src/routers/routerAdmin');
const authRouter = require('./src/routers/routerAuth');
const {
saveOriginalUrl,
ensureAuthenticated,
} = require("./src/config/middlewares");
const PORT = process.env.PORT || 3000;
app.use(morgan('tiny'));
app.use(express.static(path.join(__dirname, '/public/')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(
session({
secret: "globomantics",
resave: false,
saveUninitialized: true, // Убедитесь, что неинициализированные сессии сохраняются
cookie: {
secure: false, // установка этого значения в false для http соединений
maxAge: 3600000,
expires: new Date(Date.now() + 3600000),
},
})
);
require('./src/config/passport.js')(app)
app.set('views', './src/views');
app.set('view engine', 'ejs')
app.use('/admin', adminRouter);
app.use('/auth', authRouter);
app.use("/sessions", saveOriginalUrl, ensureAuthenticated, sessionRouter);
middlewares.js
“
function saveOriginalUrl(req, res, next) {
console.log("saveOriginalUrl");
if (!req.user && req.originalUrl) {
console.log("Сохранение оригинального URL:", req.originalUrl);
req.session.returnTo = req.originalUrl;
}
next();
}
function ensureAuthenticated(req, res, next) {
console.log("EnsureAuthenticated вызван, сессия:", req.session);
if (req.isAuthenticated()) {
return next();
}
res.render("./signin"); // Перенаправление на страницу входа, если не аутентифицирован
}
module.exports = {
saveOriginalUrl,
ensureAuthenticated,
};
“
routerAuth.js
authRouter
.route("/signin")
.get((req, res) => {
res.render("signin");
})
.post(
passport.authenticate("local", { failureRedirect: "/" }), // Обработка только перенаправления при ошибке
(req, res) => {
console.log("Сессия перед перенаправлением:", req.session);
// После успешной аутентификации обрабатываем перенаправление вручную
const redirectTo = req.session.returnTo || "/auth/profile"; // По умолчанию "/auth/profile", если нет returnTo
console.log("Перенаправление на:", req.session.returnTo);
delete req.session.returnTo; // Очищаем сессию после перенаправления
res.redirect(redirectTo);
}
);
module.exports = authRouter;
Таким образом, код работает нормально, кроме того факта, что моя переменная сессии redierctTo, установленная в middleWares.js, является неопределенной после аутентификации, и моя страница перенаправляется на путь по умолчанию ‘auth/profile’. Что я делаю не так?
Ответ или решение
Проблема, с которой вы столкнулись, связана с тем, что переменная сессии returnTo
, которая устанавливается в вашем промежуточном программном обеспечении saveOriginalUrl
, не сохраняется должным образом, и, как результат, оказывается неопределенной после процесса аутентификации. Давайте проанализируем ваш код и возможные причины.
Причины проблемы
-
Отсутствие повторной проверки аутентификации: Если промежуточное программное обеспечение
saveOriginalUrl
не успевает выполниться до того, как будет вызваноpassport.authenticate
в маршруте/signin
, тогда значениеreq.session.returnTo
останется неопределенным. - Порядок выполнения промежуточных обработчиков: Убедитесь, что аутентификация происходит после срабатывания
saveOriginalUrl
. Это важно, поскольку если пользователь не аутентифицирован, переменнаяreq.session.returnTo
автоматически не будет установлена.
Решение
-
Проверка порядка промежуточных обработчиков: Убедитесь, что на момент вызова
passport.authenticate
уже выполнен ваш промежуточный обработчикsaveOriginalUrl
. Это значит, что вам нужно перенести его вызов в соответствующий маршрут, чтобы он всегда выполнялся перед аутентификацией. - Использование правильного порядка маршрутизации: Например, перед
passport.authenticate
необходимо добавитьsaveOriginalUrl
в ваш маршрут/signin
. Вот как это может выглядеть:
// routerAuth.js
authRouter
.route("/signin")
.get((req, res) => {
res.render("signin");
})
.post(
saveOriginalUrl, // Добавьте сюда свой middleware для сохранения оригинального URL
passport.authenticate("local", { failureRedirect: "/" }), // Только обрабатывайте неудачную аутентификацию
(req, res) => {
console.log("Session before redirect:", req.session);
// После успешной аутентификации обработайте редирект вручную
const redirectTo = req.session.returnTo || "/auth/profile"; // По умолчанию перенаправляем на "/auth/profile", если нет returnTo
console.log("Redirecting to:", redirectTo);
delete req.session.returnTo; // Очистите сессию после перенаправления
res.redirect(redirectTo);
}
);
module.exports = authRouter;
Дополнительные моменты
-
Проверьте, чтобы сессии были правильно настроены и сохранялись в базу данных или в памяти. Параметры, переданные в
express-session
, такие какresave
,saveUninitialized
, могут влиять на поведение сессий, как у вас это реализовано. В вашем случае они выставлены правильно для большинства сценариев. - Не забудьте добавить отладочные сообщения (
console.log
) в местах, где устанавливаются и читаются значения сессии, чтобы лучше отслеживать процесс.
После внесения этих изменений, ваш код должен работать корректно, и req.session.returnTo
будет установлен правильно, что позволит вам перенаправить пользователя туда, откуда он пришёл, после успешной аутентификации.