Node.js не сохраняет URL перенаправления в переменной сессии, установленной в промежуточном ПО

Вопрос или проблема

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, не сохраняется должным образом, и, как результат, оказывается неопределенной после процесса аутентификации. Давайте проанализируем ваш код и возможные причины.

Причины проблемы

  1. Отсутствие повторной проверки аутентификации: Если промежуточное программное обеспечение saveOriginalUrl не успевает выполниться до того, как будет вызвано passport.authenticate в маршруте /signin, тогда значение req.session.returnTo останется неопределенным.

  2. Порядок выполнения промежуточных обработчиков: Убедитесь, что аутентификация происходит после срабатывания saveOriginalUrl. Это важно, поскольку если пользователь не аутентифицирован, переменная req.session.returnTo автоматически не будет установлена.

Решение

  1. Проверка порядка промежуточных обработчиков: Убедитесь, что на момент вызова passport.authenticate уже выполнен ваш промежуточный обработчик saveOriginalUrl. Это значит, что вам нужно перенести его вызов в соответствующий маршрут, чтобы он всегда выполнялся перед аутентификацией.

  2. Использование правильного порядка маршрутизации: Например, перед 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 будет установлен правильно, что позволит вам перенаправить пользователя туда, откуда он пришёл, после успешной аутентификации.

Оцените материал
Добавить комментарий

Капча загружается...