【问题标题】:Express Session Not Persisting Between Requests请求之间不存在快速会话
【发布时间】:2018-08-23 09:01:33
【问题描述】:

我在使用 express-session 时遇到问题。会话数据在请求之间没有持久化。

正如您在下面的代码中看到的,/join 路由设置了一些会话属性,但是当/surveys 路由被命中时,会话数据不可用。 req.session.loggedIn/surveys 路由中返回undefined

require('dotenv').config()

const cors = require('cors')
const express = require('express')
const open = require('amqplib').connect(process.env.RABBIT_SERVER)
const session = require('express-session')
const subscribeValidator = require('./src/validators/subscribe')
const { validationResult } = require('express-validator/check')

const app = express()

app.set('trust proxy', 1)
app.use(session({
  name: 'giro',
  secret: process.env.SESSION_SECRET,
  saveUninitialized: false,
  cookie: { secure: false },
  maxAge: process.env.SESSION_EXPIRY,
  resave: false
}))
app.use(express.json())
app.use(cors())

app.post('/join', subscribeValidator, function (req, res) {
  /*
  if(session.loggedIn) {
    return res.send(JSON.stringify({
      redirect: '/surveys'
    }))
  }
  */

  const data = {
    firstname: req.body.firstname,
    surname: req.body.surname,
    email: req.body.email,
    birthday: req.body.birthday,
    gender: req.body.gender,
    isSubscribed: req.body.isSubscribed
  }

  const errors = validationResult(req.body)
  if (!errors.isEmpty()) {
    return res.status(422).json({ errors: errors.array() })
  }

  open
    .then(conn => conn.createChannel())
    .then(ch => ch
      .assertQueue('subscribe')
      .then(ok => {
        ch.sendToQueue('subscribe', Buffer.from(JSON.stringify(data)))

        req.session.firstname = data.firstname
        req.session.email = data.email
        req.session.isSubscribed = data.isSubscribed
        req.session.confirmed = false
        req.session.loggedIn = true

        req.session.save()
        res.send(JSON.stringify({
          redirect: '/surveys',
          firstname: data.firstname,
          email: data.email
        }))
      })
    )
    .catch(console.warn)
})

app.post('/surveys', (req, res) => {
  console.log(req.session.loggedIn)
  if (!req.session.loggedIn) {
    return res.send(JSON.stringify({
      error: {
        type: 'auth',
        message: 'You must be logged in to view and complete surveys. Have you signed up?'
      }
    }))
  }

  res.send(JSON.stringify({
    surveys: [
      'one',
      'two',
      'three'
    ]
  }))
})

// Start the server :)
app.listen(3000, () => 
  console.log('Server running at: http://localhost:3000')
)

我检查了许多与我的问题无关的 SO 帖子,一遍又一遍地阅读文档,但我似乎仍然遗漏了一些东西。

谢谢

【问题讨论】:

  • 什么是客户端?浏览器?还是其他一些程序化请求?
  • 客户端是浏览器。
  • 这些路由是常规浏览器请求吗?还是这些ajax调用?我看到你启用了 COR。这些请求是否来自与该主机不同域的网页?您是否在浏览器中查看过所需的会话 cookie 是否存在?您是否在服务器上记录了 cookie 以查看是否存在所需的 cookie?您可以转到 Chrome 调试器中的网络选项卡,查看客户端针对任何给定请求从服务器发送和接收的所有内容(包括 cookie)。
  • cookie 已加密,但 cookie 存在于浏览器中。请求在locahost:1313 上发出,api 在localhost:3000 上。我可以毫无问题地向 API 发出请求和从 API 发出请求,但我不认为 CORS 是 cookie 的问题。
  • 执行以下操作之一。查看浏览器中的网络选项卡,查看是否通过给定请求将 cookie 发送到服务器,或者在服务器上收到给定请求时记录 cookie 的值。您需要首先确定浏览器是否正在向服务器发送 cookie。查看浏览器中的网络选项卡还将向您显示浏览器是否认为它必须对 OPTIONS 请求进行飞行前检查,以及从中得到什么。

标签: express express-session


【解决方案1】:

在@jfriend00 的帮助下,我能够解决问题。因为 API 与发出请求的 CDN 位于不同的端口上,所以当从 CDN 向 API 发出 xhr 请求时,它属于跨源请求。虽然我启用了 cors 以使 cookie 跨源工作,但您必须进行一些调整。

首先我必须像这样配置express-cors

app.use(cors({
  origin: 'http://localhost:1313',
  credentials: true
}))

这会将Access-Control-Allow-Origin 标头值设置为http://localhost:1313。不能使用通配符,否则会导致飞行前检查失败。

crednetials 属性将Access-Control-Allow-Credentials 标头值设置为true。同样,如果没有这个,预飞行将失败。

在主机上发出请求时,我还必须使用withCredentials。我正在使用超级代理,所以我这样做了:

componentDidMount () {
    request
      .post('http://localhost:3000/surveys')
      .withCredentials()
      .set('accept', 'json')
      .end((err, res) => {
        this.setState({ isLoading: false })
        ...
      })
}

现在它可以工作了:)

【讨论】:

  • 谢谢,添加了withCredentials(credentials:"include"),现在会话持续进行。
猜你喜欢
  • 2016-04-12
  • 2017-12-28
  • 1970-01-01
  • 2019-10-13
  • 2023-03-15
  • 2020-07-01
  • 2021-05-30
  • 2016-07-06
  • 2014-08-28
相关资源
最近更新 更多