为什么我的“req.session”没有创建会话?

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

我目前正在 React/Express 中创建一个应用程序,并且正在学习如何创建会话。我正在使用快速会话,因为这是每个人都推荐的,但我有意想不到的行为。
在我的路线帖子中,连接期间使用的路线,我尝试为用户创建一个新会话,但它似乎不起作用(没有 cookie 并且未创建会话),而我的 console.log 返回了预期的信息。

router.post('/login', async (req, res) => {
    const user = await Users.findOne({where: {Email: req.body.Email}})
    if (!user) res.json({error: "User doesn't exist"})
    bcrypt.compare(req.body.Password, user.Password).then((match) => {
        if (!match) res.json({error: "Wrong password"})
        req.session.user = user.dataValues
        console.log(req.session)
    })
})

在每次刷新页面时调用的 get 路由中,我意识到会话是空的,并且创建了一个新的 cookie(我真的不知道为什么)。

router.get('/login', async  (req, res) => {
    console.log(req.session)
    if (req.session.user) {
        res.send({loggedIn: true, user: req.session.user})
    } else {
        res.send({ loggedIn: false})
    }
})

这是我如何设置快速会话以及cors(我读到问题可能来自那里,但一切似乎都是正确的)。

app.use(cors({
    origin: ["http://localhost:3000"],
    methods: ["GET", "POST"],
    credentials: true //permet d'activer les cookies
}))

app.use(session({
    key: "userId",
    secret: "foo",
    resave: false,
    saveUninitialised: true,
    cookie: {
        expires: 60 * 60 * 24
    },
}))

我还了解到问题可能来自 API 调用,我使用 Axios,并且我小心地在调用之前添加了行

Axios.defaults.withCredentials = true

node.js session axios express-session
2个回答
1
投票

您的

router.post("/login", ...)
路由永远不会向客户端发送任何响应。快速会话的工作原理是与浏览器建立 cookie,浏览器将在将来的请求时发回该 cookie。该 cookie 包含一个加密的会话密钥,它是使会话成为可能的魔力。当您不从
/login
POST 发回任何响应时,该 cookie 永远不会返回到浏览器,因此会话 cookie 无法在将来的请求中发回,因此会话不起作用。

相反,来自浏览器的下一个请求不会有会话 cookie,因此 Express 将尝试创建另一个新的空会话。

要解决这部分问题,请从您的 POST 请求发回响应:

router.post('/login', async (req, res) => {
    const user = await Users.findOne({where: {Email: req.body.Email}})
    if (!user) res.json({error: "User doesn't exist"})
    bcrypt.compare(req.body.Password, user.Password).then((match) => {
        if (!match) res.json({error: "Wrong password"})
        req.session.user = user.dataValues;
        console.log(req.session)
        res.send("some response");      // <== send some response here
    }).catch(err => {
        // some error handling here
        console.log(err);
        res.sendStatus(500);
    });
});

为了更完整和集中的错误处理,您可以使用 http 状态来反映实际错误,您可以执行以下操作:

class myError extends Error {
    constructor(message, status) {
        super(message);
        this.status = status;
    }
}

router.post('/login', async (req, res) => {
    try {
        const user = await Users.findOne({where: {Email: req.body.Email}})
        if (!user) throw new MyError("User doesn't exist", 404) ;
        
        const match = await bcrypt.compare(req.body.Password, user.Password);
        if (!match) throw new MyError("Wrong password", 401);
        
        req.session.user = user.dataValues;
        console.log(req.session);
        res.json({loggedIn: true});
    } catch(e) {
        const status = e.status || 500;
        res.status(status).json({error: e.message});
    }
});

注意,我已经停止将

await
.then()
混合使用,这不被认为是好的风格,然后使用
try/catch
throw
将更全面的错误处理集成到一个位置。


0
投票

因此,由于某种原因,我的问题 Next.js 13(

app
目录)没有将我的 cookie 发送回 Express。我正在使用
express-session
cors
。我已经设法通过在标题上设置
Cookie
来修复。

关于 Next.js

router.ts

import {NextRequest, NextResponse} from "next/server";

export async function POST(request: NextRequest) {
  // This will get all cookies value. You can use next/headers
  // do get specific cookie key-value
  const cookies = request.headers.get("cookie");

  const req = await fetch("http://localhost:8080", {
    method: "POST",
    headers: {
      // Make sure to include cookies in your request
      // So your express-session is able to read connect.sid
      Cookie: cookies!
    },
    // By default Next.js will cache your routes.
    // For development purpose, if your API business
    // logic, changes constantly, I suggest using "no-cache"
    cache: "no-cache",
    credentials: "include"
  });

  const resp = await req.json();

  if (req.status === 200) {
    return NextResponse.json({ message: "Success" }, { status: 200 });
  } else {
    return NextResponse.json({ message: "Internal Server Error", { status: 500 });
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.