【问题标题】:How to deal with the server sending two different cookies for consecutive requests?如何处理服务器为连续请求发送两个不同的 cookie?
【发布时间】:2020-12-12 07:55:50
【问题描述】:

当我在同一页面上发出两个同步的连续提取请求时,服务器会为该客户端创建两个不同的会话。这是因为第二个请求发送到服务器之前第一个响应将 Set-Cookie 标头发送回客户端。

控制台显示两个请求都没有发送 cookie。因此,两个响应都创建了一个新会话。

-----------'/first' request------------
'req.headers.cookie: undefined
'req.sessionID: uZCc-2EtuOIdqD5xfcBCBLQjZbRmy29k
'/first' Set-Cookie header: connect.sid=s%3AuZCc-2EtuOIdqD...

-----------'/second' request------------
'req.headers.cookie: undefined
'req.sessionID: Gzr5CPYvE5deGA-Ul7EwOzHbaWFtpXR3
'/second' Set-Cookie header: connect.sid=s%3AGzr5CPYvE5deGA... 

当您取消注释 // await addNSecondsDelay(5);(请记住清除要复制的 cookie)以创建 5 秒延迟时,您可以进一步看到此问题是由于第二个请求触发过快引起的。这将只创建一个会话。

我不希望每次新客户访问具有多个请求的页面时都创建额外的未使用会话。我可以想出一些方法来解决这个问题——比如异步调用 fetch——但这似乎不适合更复杂的情况,比如动态创建 html 页面并且你不能将每个动态生成的 fetch 调用链接在一起零件。这似乎也会减慢页面加载速度。

是否有适当的方法来确保不创建两个会话?

后端服务器

// other-server.js
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');

const app = express();
const sess = {
  saveUninitialized: false,
  resave: false,
  secret: 'very secret 12345',
  cookie: {
    sameSite: true,
    secure: false,
  },
};

app.use(bodyParser.json());
app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(session(sess));

app.use((req, res, next) => {
  console.log(`\n-----------'${req.path}' request------------`);

  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Accept, Content-Type');
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5001');
  res.setHeader('Access-Control-Allow-Credentials', true);
  res.setHeader(
    'Access-Control-Allow-Methods',
    'GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH'
  );
  res.on('close', function () {
    console.log(
      `'${req.path}' Set-Cookie header: ${res.getHeaders()['set-cookie'][0].slice(0, 30)}...`
    );
  });
  req.session.a = 'hi';
  console.log(`'req.headers.cookie: ${req.headers.cookie}`);
  console.log(`'req.sessionID: ${req.sessionID}`);
  next();
});
app.post('/first', (req, res) => {
  res.json({ message: "1st fetch's response" });
});
app.post('/second', (req, res) => {
  res.json({ message: "2nd fetch's response" });
});

app.listen(4001, () => {
  console.log('start');
});

前端服务器

// server.js
const express = require('express');

const app = express();
app.use(express.static('./public'));
app.listen(5001);

index.html

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <script>
      const addNSecondsDelay = (n) => {
        console.log('5 second delay ...');
        return new Promise((resolve) => {
          setTimeout(() => {
            resolve();
          }, n * 1000);
        });
      };

      const asyncFunctionCall = async () => {
        fetch('http://localhost:4001/first', {
          method: 'POST',
          credentials: 'include',
        })
          .then((response) => {
            return response.json();
          })
          .then((json) => {
            console.log('Received:  ' + JSON.stringify(json));
          });
        // await addNSecondsDelay(5);
        fetch('http://localhost:4001/second', {
          method: 'POST',
          credentials: 'include',
        })
          .then((response) => {
            return response.json();
          })
          .then((json) => {
            console.log('Received:  ' + JSON.stringify(json));
          });
      };

      asyncFunctionCall();
    </script>
  </body>
</html>

【问题讨论】:

  • 你能在加载网页的服务器上运行 API 吗?如果是这样,那么在您的任何 Javascript 运行之前,将网页加载到浏览器中的行为就已经在浏览器中设置了会话 cookie。
  • @jfriend00 对于我的具体用例,我希望将它们分开,但很高兴知道
  • 我实际上意识到我不需要两台不同的服务器,所以我接受了这个建议。谢谢

标签: node.js express http session cookies


【解决方案1】:

理想的解决方案是在加载网页的同一台服务器上运行 API?如果是这样,那么在网页中的任何 Javascript 运行之前,将网页加载到浏览器中的行为就已经在浏览器中设置了会话 cookie。

【讨论】:

    【解决方案2】:

    这些是您的选择:

    1. 在您执行任何其他操作之前发送 1 个请求,因此您只会得到一个 cookie。
    2. 让拥有 2 个 cookie 无关紧要。

    您收到的最后一个Set-Cookie 标头'wins',并且没有好方法知道这两个请求确实来自同一个客户端(这就是cookie 的用途),所以您不能直接 轻松解决这个问题。

    我能想到的唯一其他选择是让客户端自己生成一些唯一的 id 并将其与两个请求一起发送,但我怀疑这在安全性方面也是一个蠕虫罐头。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-09
      • 2017-06-04
      • 2014-03-04
      • 2014-04-30
      • 2012-10-23
      • 1970-01-01
      • 2016-08-05
      • 2015-08-08
      相关资源
      最近更新 更多