NodeJS 当我呼叫其他路由时,为什么我的会话数据不显示在其他路由上?

eagi6jfj  于 2023-01-16  发布在  Node.js
关注(0)|答案(1)|浏览(109)

我想使用我的登录数据(用户名、ID)并将它们存储在其他表中,以便访问存储在这些表中的其他数据。我对服务器使用Node.js和express,对会话使用express-session模块。以下是app.js和会话中间件及其默认选项

import session from 'express-session';
app.use(session({
  name:'test',
  secret: "thisismysecrctekeyfhrgfgrfrty84fwir767",
  saveUninitialized: true,
  resave: false
}));
//some other stuff
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((_, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
 });
app.use((req,res,next) => {
  console.log('req.session',req.session);
  next();
});

在此之后,我使用路由器为我所有的路线,这里是登录路线,我保存我的用户名到会话中

router.post('/login', (req, res, next) => {
    // checks if email exists
      User.findOne({ where : {   //
          name: req.body.name,   //
      }})
      .then(dbUser => {
        if (!dbUser) {
            return res.status(404).json({message: "user not found"});
        } else {
            // password hash
            bcrypt.compare(req.body.password, dbUser.password, (err, compareRes) => {
                if (err) { // error while comparing
                    res.status(502).json({message: "error while checking user password"});
                } else if (compareRes) { 
                    // password match
                    const token = jwt.sign({ name: req.body.name }, 'secret', { expiresIn: '1h' });     
                    const sessName= req.body.name;
                    req.session.name=sessName;
                    res.status(200).json({message: "user logged in", "token": token});
                } else { // password doesnt match
                    res.status(401).json({message: "invalid credentials"});
                };
            });
        };
    })
    .catch(err => {
        console.log('error', err);
    });
});

用户输入登录信息后,将从登录路径转到身份验证路径

router.get('/private', (req, res, next) => {
    const authHeader = req.get("Authorization");
    if (!authHeader) {
        return res.status(401).json({ message: 'not authenticated' });
    };
    const token = authHeader.split(' ')[1];
    let decodedToken; 
    try {
        decodedToken = jwt.verify(token, 'secret');
    } catch (err) {
        return res.status(500).json({ message: err.message || 'could not decode the token' });
    };
    if (!decodedToken) {
        res.status(401).json({ message: 'unauthorized' });
    } else {
        res.status(200).json({ message: `here is your resource ${req.session.name}` });
    };
});

如果我控制台记录会话,它会显示终端上的用户名,对于其他路由,当我将一些数据存储到会话上并从其他路由访问它时,它工作正常,但当我从登录路由存储用户名时,当我尝试访问它时,它不会显示。

router.get('/session', (req,res,next)=>{
    if (req.session.name) {
      res.json({name: req.session.name})
    } else {
      res.json({name: null});
    }
})

我是Node.js的新手,所以如果有人能回答这个问题会很有帮助。
之后

const sessName= req.body.name;
req.session.name=sessName;

这个名字从登录路径保存在会话中,但是当我从其他路径访问它时,它显示了一个空值。2另外,当我重新启动服务器后,会话结束和用户名消失是正常的吗?

dy1byipe

dy1byipe1#

由于/login/private看起来都像是由代码生成的,所以问题可能是由于代码没有捕获会话cookie、保留它并确保它与代表同一用户的所有后续请求一起发送。
会话cookie是快速会话工作的关键。在第一次与客户端参与度时,快速会话中间件发现没有会话cookie附加到这个请求上。它创建一个新的会话cookie,其中包含一个加密的唯一密钥,将该密钥添加到内部会话存储中,并将该cookie与http响应一起返回。
要使会话正常工作,接收该cookie的客户机必须保留该cookie,并将其与来自该客户机的所有未来http请求一起发送(直到它过期)。由于这些对/login/private的HTTP请求是通过编程进行的,您的代码必须正确设置以保留和发送此cookie。这将取决于你使用什么http库来发出这些http请求,你如何确切地去保留和重新发送会话cookie。
如果这些请求是由运行在浏览器中的Javascript在网页中生成的,那么浏览器将为您保留Cookie,您只需要对http请求进行适当的设置,以确保Cookie被发送。如果您正在进行跨源请求,那么事情会变得有点复杂。
如果这些cookie是由你自己的代码在你自己的应用程序中生成的,那么包含cookie的具体步骤将取决于你使用的http库,许多http库都有一个通常被称为cookie jar的东西,它可以与给定的请求/响应相关联,以帮助维护和发送cookie。
现在你已经展示了你的客户端代码,代码使用fetch()来进行这些调用,这就是你的客户端正在使用的http请求库。
由于这可能是一个跨源请求,为了确保cookie随fetch()发出的请求一起发送,您可以添加credentials: "include"选项,如下所示:

fetch(`${API_URL}/private`, {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`, 
        },
        credentials: "include",
    }).then(...)

如果fetch()不发送凭据(包括cookie),那么您的会话cookie将不会被发送,您的服务器将认为它必须在每个新请求上创建一个新会话,这样您的会话将永远不会从一个请求到下一个请求被维护。

相关问题