【问题标题】:node express-session not saving across pages节点快速会话不跨页面保存
【发布时间】:2019-12-23 14:43:08
【问题描述】:

我不知道为什么当我转到 localhost:8080 时它会保存会话(似乎是),但是当我转到下一个 URL localhost:8080/me 时,会话又是空的。

const express = require("express");
const app = express();
const port = 8080;
const router = express.Router();
const session = require('express-session');

app.use(session({
  secret: 'work hard',
  resave: true,
  saveUninitialized: false
}))

app.get("/", function(req,res, next){
    req.session.myname = "nathan";
    console.log(req.session.myname);
});


app.get("/me", function(req,res, next){

    console.log(req.session.myname);
});

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

当我尝试下面第一个贡献者(在答案中)所示的 app.sendStatus 方法时,它可以工作,但如果我使用 ajax 则不行???

    $("#register").on("click", function(){
         $.ajax({url: "http://localhost:8080/"});
    });


    $("#me").on("click", function(){
         $.ajax({url: "http://localhost:8080/me"});
    });

【问题讨论】:

    标签: node.js express npm express-session


    【解决方案1】:

    原因是您没有向客户端发送带有set-cookie 标头的响应。

    Set-Cookie HTTP 响应头用于将 cookie 从服务器发送到用户代理,因此用户代理可以稍后将它们发送回服务器。

    您可以使用res.sendStatus()res.send()res.end()res.json() 等发送回复给客户。

    例如

    app.js:

    const express = require('express');
    const app = express();
    const port = 8080;
    const router = express.Router();
    const session = require('express-session');
    const fs = require('fs');
    const path = require('path');
    
    app.use(
      session({
        secret: 'work hard',
        resave: true,
        saveUninitialized: false,
      }),
    );
    
    app.get('/', function(req, res, next) {
      req.session.myname = 'nathan';
      console.log(req.session.myname);
      const htmlContent = fs.readFileSync(path.resolve(__dirname, './public/app.html')).toString();
      res.send(htmlContent);
    });
    
    app.get('/me', function(req, res, next) {
      console.log(req.session.myname);
      res.sendStatus(200);
    });
    
    app.get('/ajax', function(req, res) {
      console.log('req.session.myname: ', req.session.myname);
      res.sendStatus(200);
    });
    
    app.listen(port, () => console.log(`Example app listening on port ${port}!`));
    

    完成此操作后,您的客户端(可以是浏览器)将收到这些响应标头:

    HTTP/1.1 200 OK
    X-Powered-By: Express
    Content-Type: text/plain; charset=utf-8
    Content-Length: 2
    ETag: W/"2-nOO9QiTIwXgNtWtBJezz8kv3SLc"
    set-cookie: connect.sid=s%3A-QI2kuY8IlxdAZw96xqG_npmuKwFhg0s.tKcPZgcHhHvXG0kqgKzwzJJ7kn2JkPOMG9R%2FyQaJwPw; Path=/; HttpOnly
    Date: Mon, 23 Dec 2019 06:00:24 GMT
    Connection: keep-alive
    

    浏览器会自动设置cookie。然后,你转到下一个/me 路由,浏览器会自动发送这个带有请求头的cookie。

    例如

    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    Cache-Control: no-cache
    Connection: keep-alive
    Cookie: connect.sid=s%3A-QI2kuY8IlxdAZw96xqG_npmuKwFhg0s.tKcPZgcHhHvXG0kqgKzwzJJ7kn2JkPOMG9R%2FyQaJwPw
    Host: localhost:8080
    Pragma: no-cache
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
    

    在您的服务器端/me 控制器中,express-session 中间件将解析cookie,您将从req.session.myname 属性中获取myname 的值。

    更新

    ./public/app.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>
        <main>
          app
          <button id="me">Click Me</button>
        </main>
        <script
          src="https://code.jquery.com/jquery-3.4.1.min.js"
          integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
          crossorigin="anonymous"
        ></script>
        <script>
          window.onload = function() {
            $('#me').on('click', function() {
              $.ajax({ url: 'http://localhost:8080/ajax' }).then(() => {
                console.log('success');
              });
            });
          };
        </script>
      </body>
    </html>
    

    您也可以获得myname 的值。这是服务器端日志:

    Example app listening on port 8080!
    nathan
            req.session.myname:  nathan
    

    【讨论】:

    • ok.... 这有帮助,但是,为什么从 ajax 调用中点击它时它不起作用?当我手动转到 localhost:8080 等时它可以工作......
    • @NathanLeggatt 看看:stackoverflow.com/questions/2870371/…
    • @NathanLeggatt 更新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 2013-11-07
    • 2019-01-24
    • 2014-06-14
    • 1970-01-01
    相关资源
    最近更新 更多