首页 > 解决方案 > 节点快速会话不跨页面保存

问题描述

我不知道为什么当我转到 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.jsexpressnpmexpress-session

解决方案


原因是您没有向客户端发送带有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,您将获得mynamefromreq.session.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

推荐阅读