typescript 当我使用express-mysql-session时,express JS - connect-flash无法正常工作

7z5jn7bk  于 2022-11-26  发布在  TypeScript
关注(0)|答案(1)|浏览(144)

我有一个奇怪的问题。我发现问题在哪里,但我不知道如何解决它。我使用cookie-parserexpress-mysql-sessionexpress-sessionconnect-flashpassport等在我的项目中。为了在mySQL database中存储会话,我使用express-mysql-session模块。但这个模块使connect-flash出现问题。这是我配置第一个中间件的地方:

const setFirstMiddleWares = (server: Express) => {
  if (devMode) server.use(morgan("dev"));
  
  server.use(bodyParser.urlencoded({ extended: false }));
  server.use(cookieParser());
  server.use(
    expressSession({
      secret: "secret",
      saveUninitialized: false,
      resave: false,
      store: MySQLSessionStore, //the problem is exactly this line
    })
  );
  server.use(flash());
  server.use(passport.initialize());
  server.use(passport.session());
  server.use(setRenderConfig);
};

express-mysql-sessionconnect-flash造成的问题是,当我在中间件中设置一个消息connect-flash,然后我将用户重定向到例如登录页面时,第一次没有消息显示在视图中。但当我刷新登录页面时,消息将显示!但当我删除express-session配置对象的存储属性时,一切都会很好,用户重定向到登录页面后,flash消息将立即显示在登录视图中,登录页面不需要刷新来显示错误或成功消息!这对于flash-connect来说确实是一个奇怪的行为。您可以看到我的代码的重要部分:DB.ts:

mport mysql from "mysql2/promise";
import MySQLStoreSessionsStore from "express-mysql-session";
import * as expressSession from "express-session";

const dbConfig = {
  host: process.env.DBHOST,
  user: process.env.DBUSER,
  password: process.env.DBPASSWORD,
  port: Number(process.env.DBPORT),
  database: process.env.DATABASENAME,
};

const connection = mysql.createPool(dbConfig);
const MySQLSessionStoreClass = MySQLStoreSessionsStore(expressSession);
const MySQLSessionStore = new MySQLSessionStoreClass({}, connection);

export { connection as mysql, MySQLSessionStore };

Users.ts:

import { NextFunction, Request, Response } from "express";
import passport from "passport";
import { signUpUser } from "../models/Users";
const signUpUserController = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  try {
    await signUpUser(req.body);
    req.flash("sign-in-successes", [
      "your account has been created successfully! please login to your account.",
    ]);
    res.redirect("/login");
  } catch (errors) {
    if (Array.isArray(errors)) {
      req.flash("sign-up-errors", <string[]>errors);
      res.redirect("/sign-up");
    } else next({ error: errors, code: "500" });
  }
};

const signInUserController = (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  passport.authenticate("local", {
    failureRedirect: "/login",
    failureFlash: true,
  })(req, res, next);
};

const remmemberUserController = (req: Request, res: Response) => {
  console.log("line 5:", req.body);
  if (req.body["remmember-user"]) {
    req.session.cookie.originalMaxAge = 253402300000000;
  } else {
    req.session.cookie.expires = undefined;
  }

  res.redirect("/account/dashboard");
};

const logOutController = (req: Request, res: Response, next: NextFunction) => {
  req.logOut({ keepSessionInfo: false }, (err) => {
    console.log(err);

    req.flash("sign-in-successes", ["logged out successfuly!"]);
    res.redirect("/login");
  });
};

export {
  signUpUserController,
  signInUserController,
  logOutController,
  remmemberUserController,
};

passport.ts:

import passport from "passport";
import localStrategy from "passport-local";
import bcrypt from "bcrypt";
import { getUsersInfos } from "../models/Users";

passport.use(
  new localStrategy.Strategy(
    {
      usernameField: "user-email-signin",
      passwordField: "user-password-signin",
    },
    async (email, password, done) => {
      try {
        const user: any = await getUsersInfos(email);

        if (Array.isArray(user)) {
          const length: 2 | number = user.length;
          if (length === 0) {
            return done(null, false, {
              message: "user with your entered email not found!",
            });
          }

          const isMatch = await bcrypt.compare(password, user[0].password);

          if (isMatch) {
            return done(null, user);
          } else {
            return done(null, false, {
              message: "email or password are incorrect!",
            });
          }
        } else {
          return done(null, false, {
            message: "something went wrong. please try again!",
          });
        }
      } catch (error) {
        console.log(error);
      }
    }
  )
);

passport.serializeUser((user, done) => {
  done(null, user);
});

passport.deserializeUser(async (user, done) => {
  if (Array.isArray(user)) {
    done(null, user[0].id);
  }
});

LoginController.ts:

import { Request } from "express";
import { NewExpressResponse } from "../types/Types";

const loginController = (req: Request, res: NewExpressResponse) => {
  res.render("login", {
    title: `login`,
    scripts: [...res.locals.scripts, "/js/LoginScripts.js"],
    successes: req.flash("sign-in-successes"),
    error: req.flash("error"),
  });
};

export { loginController };

我在谷歌搜索了很多这个问题,但我发现的唯一一件事是,我应该在我的中间件中使用req.session.save(() => { res.redirect("/login");})来显示用户重定向到路由后立即在视图中的flash消息.但这种方式有一些问题:
1.我应该使用这个代码为每一个重定向,如果我想设置和使用的flash消息在重定向路由,我其实不喜欢这个。
1.我不能在signInUserController中做这样的事情,因为passport自己在flash中设置错误。
那么,当我使用express-mysql-session时,你有什么想法来修复connect-flash的这种奇怪行为吗?谢谢帮助:)

rt4zxlrg

rt4zxlrg1#

我发现这是connect-flash中的一个问题(实际上不是问题,是一个可以添加的特性)。它本身不保存会话。正因为如此,我创建了这个包的异步版本,其中包含更多特性。您可以使用promise基函数或回调基函数来保存和获取您的flash消息。因此您可以使用async-connect-flash而不是connect-flash。我希望您喜欢它:)

相关问题