Passport - req.isAuthenticated() 在本地策略之后的 /login 路由中返回 true,但在 Passport.authenticate("session") 之后的 /current-session 中不返回 true

问题描述 投票:0回答:1

我正在使用 PERN 堆栈构建一个全栈应用程序。我可以从前端

POST
输入用户名和密码到
/login
并成功登录 -
isAuthenticated()
返回true。但是,如果我随后向
GET
发送
/current-session
请求,
isAuthenticated()
将返回 false。

我想知道哪里可能出了问题。我已经查看了 Stack Overflow 上可以找到的所有相关问题,但尚未找到答案。

服务器正在运行。数据库连接建立,对数据库进行查询工作。正在填充数据库表“会话”。例如:

希德 sess 过期
T6akfD8h0TWysQD2jZ5LqIBlxCBIcLSp [对象对象] 2024-03-06 00:54:22 +0000

在浏览器中,当我

POST
/login
时,我可以从响应标头中看到 sid 作为仅 HTTP 的 cookie。例如:

connect.sid=s%3AT6akfD8h0TWysQD2jZ5LqIBlxCBIcLSp.H01oGHOfFy9m6Tt451i%2F0vpoKuYEDPN8insL7Wx8GaU;
Path=/;
Expires=Wed, 06 Mar 2024 00:54:21 GMT;
HttpOnly

但是,当我

GET
/current-session
时,我在浏览器响应中看不到cookie。

似乎

app.use(passport.session());
出于某种原因告诉
app.get("/current-session"...
没有当前用户会话/当前经过身份验证的用户。想知道会话是否由于某种原因没有被维持......?

从我的日志中,我可以看到

passport.deserializeUser()
从未被调用过。

这是当前代码:

const express = require("express");
const session = require("express-session");
const passport = require("passport");
const LocalStrategy = require("passport-local");
const bcrypt = require("bcrypt");
const cors = require("cors");
const cookieParser = require("cookie-parser");
const { Pool } = require("pg");
const pgSession = require("connect-pg-simple")(session);
require("dotenv").config();

// -------------  GENERAL SETUP  --------------- //
const app = express();
const PORT = process.env.PORT || 3001;
app.use(
  cors({
    origin: "https://nightlifeapp.onrender.com", // "http://localhost:5173",
    credentials: true,
    "Access-Control-Allow-Credentials": true,
  })
);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

// -----------  DATABASE CONNECTION  ----------- //
// Create a PostgreSQL connection pool
const pool = new Pool({
  connectionString: process.env.ELEPHANTSQL_CONNECTION_URL,
  max: 5,
});

// Test the database connection
pool.connect((err, client, done) => {
  if (err) {
    console.error("Error connecting to the database", err);
  } else {
    console.log("Connected to the database");
  }
});


// -----------  PASSPORT STRATEGIES  ----------- //
passport.use(
  "local",
  new LocalStrategy((username, password, done) => {
    // Query the PostgreSQL database to find a user by username
    pool.query(
      "SELECT * FROM users WHERE username = $1",
      [username],
      (err, result) => {
        if (err) {
          return done(err);
        }
        // Check if the user exists
        const user = result.rows[0];
        if (!user) {
          return done(null, false);
        }
        // Check if the password is correct
        if (!bcrypt.compareSync(password, user.password_hash)) {
          return done(null, false);
        }
        // If the username and password are correct, return the user
        return done(null, user);
      }
    );
  })
);

passport.serializeUser((user, done) => {
  console.log("serializeUser invoked");
  done(null, user);
});
passport.deserializeUser((user, done) => {
  console.log("serializeUser invoked");
  done(null, user);
});


// -------------  EXPRESS SESSION  ------------- //
app.use(
  session({
    store: new pgSession({
      pool,
      tableName: "session",
    }),
    secret: process.env.EXPRESS_SESSION_SECRET_KEY,
    resave: false,
    saveUninitialized: false,
    cookie: {
      maxAge: 14 * 24 * 60 * 60 * 1000, // 14 days session timeout
    },
  })
);

app.use(passport.initialize());
app.use(passport.session());


// -----------------  ROUTING  ----------------- //
app.get("/current-session", passport.authenticate("session"), (req, res) => {
  if (req.isAuthenticated()) {
    console.log("At GET /current-session... isAuthenticated() returned true");
  } else {
    console.log("At GET /current-session... isAuthenticated() returned false");
  }

  if (!req.user) {
    res.json({ currentlyLoggedIn: false });
  } else {
    res.json({
      currentlyLoggedIn: true,
      userId: req.user.user_id,
      username: req.user.username,
    });
  }
});

app.post(
  "/login",
  passport.authenticate("local"), (req, res) => {
    if (req.isAuthenticated()) {
      console.log("At POST /login... isAuthenticated() returned true");
    } else {
      console.log("At POST /login... isAuthenticated() returned false");
    }

    return res.json({
      loginSuccessful: true,
      userId: req.user.user_id,
      username: req.user.username,
    });
  }
);

// ------------------  SERVER  ----------------- //
const server = app.listen(PORT, () =>
  console.log(`Server is listening on port ${PORT}`)
);

server.keepAliveTimeout = 120 * 1000;
server.headersTimeout = 120 * 1000;

在前端,我向

/login
/current-session
发出的获取请求如下:

fetch(`${URL}/login`, {
      method: "POST",
      credentials: "include",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
        "Access-Control-Allow-Origin": "https://nightlifeapp.onrender.com",
      },
      body: jsonData,
    })

还有

fetch(`${URL}/current-session`, {
      method: "GET",
      credentials: "include",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
        "Access-Control-Allow-Origin": "https://nightlifeapp.onrender.com",
      },
    })```


Any suggestions would be greatly appreciated!

node.js express authentication passport.js express-session
1个回答
0
投票

所以,事实证明,这里的问题是 cookie 被阻止,因为前端和后端托管在不同的 Render.com 子域上,因此 cookie 没有被用来保持会话继续进行.

我可以使用不同/自定义域名来避免 cookie 被阻止。

相反,我提出的解决方案是将前端静态文件托管在与 Express API 端点相同的服务器上。为此,我将 React 前端的 build/dist 文件放置在 Express 服务器上的一个文件夹中,然后使用

app.use(express.static("dist"));
为前端
index.html
文件提供服务 - 默认情况下调用 '/ ' 终点。

我用这个解释作为起点:https://youtu.be/4pUBO31nkpk?si=M5GXQGCa__W0_yH9

© www.soinside.com 2019 - 2024. All rights reserved.