且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用 Nextjs 应用程序空闲 1 分钟后 Openlitespeed 会话超时

更新时间:2023-10-19 08:35:34

好吧,我终于想通了.Openlitespeed 的配置已设置,因此它可以创建任意数量的 httpd 工作人员.因此,当创建一个新的并且请求转到那个时,似乎身份验证没有坚持.我已经通过设置工人数量"解决了这个问题.在服务器配置下为 1 ->服务器进程->工人数量.

至于我用来设置 nextjs 和 openlitespeed 的 server.js 文件:

const express = require("express");const next = require("next");const 护照 = 要求(护照");const redis = require("redis");const session = require("express-session");const { v4: uuidv4 } = require("uuid");常量路径 = 要求(路径");const log = require("./logger");let RedisStore = require("connect-redis")(session);让 redisClient = redis.createClient({ auth_pass: process.env.DB_PASSWORD });常量端口 = parseInt(process.env.PORT, 10) ||3000;const dev = process.env.NODE_ENV !== 生产";const app = next({ dev });常量句柄 = app.getRequestHandler();app.prepare().then(() => {常量服务器 = 快递();//Json解析server.use(express.json());server.use(express.urlencoded({extended: true }));如果(开发){//表达会话服务器.使用(会议({商店:新的 RedisStore({ 客户端:redisClient }),基因:函数(){返回 uuidv4();},秘密:uuidv4(),重新保存:假,保存未初始化:假,曲奇饼: {安全:假,最大年龄:86400000,},}));} 别的 {//表达会话服务器.使用(会议({商店:新的 RedisStore({ 客户端:redisClient }),基因:函数(){返回 uuidv4();},秘密:uuidv4(),代理:是的,重新保存:假,保存未初始化:假,曲奇饼: {安全:真实,最大年龄:86400000,},}));}//护照认证server.use(passport.initialize());server.use(passport.session());//导入护照配置const initializePassport = require("./passport-config");初始化护照(护照);//登录路径server.post("/login", passport.authenticate("login"), (req, res) => {res.send({ message: "成功登录", login: true });});const passportLogout = function (req, res, next) {req.logout();下一个();};//注销路由server.get("/logout", passportLogout, (req, res) => {req.session.destroy();res.redirect("/login");});//导入注册路由.加.brugen af route i stedet for app kan vi bruge denne 中间件 med en anden underside, hvis vi f.eks.ville gøre så admins også kunne lave brugere.const registerRoute = require("./routes/register-user");server.use("/register", registerRoute);//用户路由需要登录.渲染.Skal stå under call til initializepassport, ellers kan den ikke finde ud af at den er authenticated via passport, og auth.js returnerer dig derfor til loginconst usersRoutes = require("./routes/user/user-routes");server.use(usersRoutes);//管理路由直到渲染const adminRoutes = require("./routes/admin/admin-routes");server.use(adminRoutes);const indexRoutes = require("./routes/index-routes");server.use(indexRoutes);server.all("*", (req, res) => {返回句柄(req, res);});server.listen(port, (err) => {if (err) 抛出错误;console.log(`> 在 ${port} 上准备好了`);});});

Hello *** Community.

So I am encountering a very weird problem when hosting my nextjs powered by express with openlitespeed. Everything works great in production, except one thing - the authentification of sessions. The user is saved in the cookies correctly and it works if you are not idle for more than a minute on the page you are on, but if you are idle for more than a minute, then the request is not authenticated anymore even though the cookie is still there.

I am using redis for my cookie store, and everything works in local testing, where openlitespeed is not present. The authentification I am using is passportjs with express-session. Have any of you encountered this problem, and if so, how did you solve it? I have tried disabling the cache module, set all timeouts to a higher value or disabling them, use different memorystores and more, but no luck. Here is the server.js file, however, I do not believe it has something to do with the code itself, but rather the config of openlitespeed:

const express = require('express')
const next = require('next')
const passport = require('passport');
const redis = require('redis')
const session = require('express-session')
const {v4: uuidv4} = require('uuid');
const path = require('path');
const log = require('./logger')
let RedisStore = require('connect-redis')(session)
let redisClient = redis.createClient()

const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  const server = express()

  //Json parsing
  server.use(express.json());
  server.use(express.urlencoded({extended: true}));


  if (dev){
    //Express session
    server.use(session({
      store: new RedisStore({ client: redisClient }),
      genid: function() {
        return uuidv4()},
      secret: uuidv4(),
      resave: false,
      saveUninitialized: false,
      cookie: {
        secure: false,
        maxAge: 86400000 
      }
  }))
  }
  else{
      //Express session
    server.use(session({
      store: new RedisStore({ client: redisClient }),
      genid: function() {
        return uuidv4()},
      secret: uuidv4(),
      proxy: true,
      resave: false,
      saveUninitialized: false,
      cookie: {
        secure: true,
        maxAge: 86400000
      }
  }))
  }


  //Passport auth
  server.use(passport.initialize());
  server.use(passport.session());

  //Import of the passport config 
const initializePassport = require('./passport-config');
initializePassport(passport);

//Login route
server.post('/login', passport.authenticate('login'), (req, res) => {
    res.send({message: 'Successful login', login: true})
});

const passportLogout = function (req, res, next) {
  req.logout()
  next()
}

//Logout route
server.get('/logout', passportLogout, (req, res) => {
    req.session.destroy();
    res.redirect('/login');
});

//Import registrerings route. Pga. brugen af route i stedet for app kan vi bruge denne middleware med en anden underside, hvis vi f.eks. ville gøre så admins også kunne lave brugere.
const registerRoute = require('./routes/register-user');
server.use('/register', registerRoute);

  //User routes hvor login er required. Rendering. Skal stå under called til initializepassport, ellers kan den ikke finde ud af at den er authenticated via passport, og auth.js returnerer dig derfor til login
  const usersRoutes =  require('./routes/user/user-routes');
  server.use(usersRoutes);

  //Admin routes til rendering
  const adminRoutes = require('./routes/admin/admin-routes');
  server.use(adminRoutes);

  const indexRoutes = require('./routes/index-routes');
  server.use(indexRoutes);


  server.all('*', (req, res) => {
    return handle(req, res)
  })

  server.listen(port, (err) => {
    if (err) throw err
    log.logger.log({
      level: "info",
      message: `Server was started on ${port}`,
      additional: "properties",
      are: "passed along",
    });
    console.log(`> Ready on http://localhost:${port}`)
  })
})

All right, so I figured it out finally. The configuration for Openlitespeed was set, so that it could create as many httpd workers as it wants. Therefore, when a new was created and the requests went over to that one, it seems the authentification did not stick. I have fixed this by setting the "Number of Workers" to 1 under Server Configuration -> Server Process -> Number of Workers.

As for my server.js file I used to setup nextjs and openlitespeed:

const express = require("express");
const next = require("next");
const passport = require("passport");
const redis = require("redis");
const session = require("express-session");
const { v4: uuidv4 } = require("uuid");
const path = require("path");
const log = require("./logger");
let RedisStore = require("connect-redis")(session);
let redisClient = redis.createClient({ auth_pass: process.env.DB_PASSWORD });

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();

  //Json parsing
  server.use(express.json());
  server.use(express.urlencoded({ extended: true }));

  if (dev) {
    //Express session
    server.use(
      session({
        store: new RedisStore({ client: redisClient }),
        genid: function () {
          return uuidv4();
        },
        secret: uuidv4(),
        resave: false,
        saveUninitialized: false,
        cookie: {
          secure: false,
          maxAge: 86400000,
        },
      })
    );
  } else {
    //Express session
    server.use(
      session({
        store: new RedisStore({ client: redisClient }),
        genid: function () {
          return uuidv4();
        },
        secret: uuidv4(),
        proxy: true,
        resave: false,
        saveUninitialized: false,
        cookie: {
          secure: true,
          maxAge: 86400000,
        },
      })
    );
  }

  //Passport auth
  server.use(passport.initialize());
  server.use(passport.session());

  //Import of the passport config
  const initializePassport = require("./passport-config");
  initializePassport(passport);

  //Login route
  server.post("/login", passport.authenticate("login"), (req, res) => {
    res.send({ message: "Successful login", login: true });
  });

  const passportLogout = function (req, res, next) {
    req.logout();
    next();
  };

  //Logout route
  server.get("/logout", passportLogout, (req, res) => {
    req.session.destroy();
    res.redirect("/login");
  });

  //Import registrerings route. Pga. brugen af route i stedet for app kan vi bruge denne middleware med en anden underside, hvis vi f.eks. ville gøre så admins også kunne lave brugere.
  const registerRoute = require("./routes/register-user");
  server.use("/register", registerRoute);

  //User routes hvor login er required. Rendering. Skal stå under called til initializepassport, ellers kan den ikke finde ud af at den er authenticated via passport, og auth.js returnerer dig derfor til login
  const usersRoutes = require("./routes/user/user-routes");
  server.use(usersRoutes);

  //Admin routes til rendering
  const adminRoutes = require("./routes/admin/admin-routes");
  server.use(adminRoutes);

  const indexRoutes = require("./routes/index-routes");
  server.use(indexRoutes);

  server.all("*", (req, res) => {
    return handle(req, res);
  });

  server.listen(port, (err) => {
    if (err) throw err;
    console.log(`> Ready on ${port}`);
  });
});