redis 快速会话在每次请求时重置会话

yuvru6vn  于 2023-08-02  发布在  Redis
关注(0)|答案(2)|浏览(126)

我有一个VueJS项目,它使用axios来调用另一个域上的服务器。在这个服务器上,我需要在会话中保存一些值,这样就不需要在每次请求时都查找它们。
服务器是NodeJS,运行在Heroku上,我使用Redis作为内存存储。我可以成功地将数据保存到会话中,但在每次新请求时,系统都会使用新ID创建一个新会话,因此我无法访问上一次请求期间保存的值。

EDIT根据多个建议更新代码后,我在网络控制台的会话cookie上看到以下错误:

  1. Preflight Invalid Allow Credentials

字符串

编辑2我通过添加“credentials:true”到corsOptions。这解决了我在网络会话中看到的错误,但我仍然为每个请求获得新的会话ID。

服务器上的代码:

  1. const express = require('express');
  2. const app = express();
  3. const cors = require('cors');
  4. var corsWhitelist = ['http://127.0.0.1:8080','http://127.0.0.1:8081']
  5. var corsOptions = {
  6. origin: function (origin, callback) {
  7. if (corsWhitelist.indexOf(origin) !== -1) {
  8. callback(null, true)
  9. } else {
  10. callback(new Error('Not allowed by CORS - '+origin))
  11. }
  12. },
  13. credentials: true
  14. }
  15. let REDIS_URL = process.env.REDIS_URL;
  16. var Redis = require('ioredis');
  17. const session = require('express-session');
  18. const cookieParser = require('cookie-parser');
  19. const RedisStore = require('connect-redis')(session);
  20. const sessionClient = new Redis(REDIS_URL)
  21. sessionClient.on('error', function (err) {
  22. console.log('could not establish a connection with redis. ' + err);
  23. });
  24. sessionClient.on('connect', function (err) {
  25. console.log('connected to redis successfully');
  26. });
  27. app.set('trust proxy', 1)
  28. app.use(cookieParser());
  29. app.use(session({
  30. store: new RedisStore({ client: sessionClient }),
  31. secret: 'someSecret',
  32. resave: false,
  33. saveUninitialized: true,
  34. cookie: {
  35. secure: false,
  36. httpOnly: false,
  37. maxAge: 1000 * 60 * 10
  38. }
  39. }))
  40. app.use(cors(corsOptions));
  41. app.options('*', cors(corsOptions))
  42. // Add headers
  43. app.use(function (req, res, next) {
  44. if (corsWhitelist.indexOf(req.headers.origin) !== -1) {
  45. res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
  46. res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  47. res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  48. res.setHeader('Access-Control-Allow-Credentials', 'true');
  49. }
  50. next();
  51. });
  52. const getUser = async function(req, res, next) {
  53. if (!req.session.user) {
  54. req.session.user = "test@example.com"
  55. req.session.save()
  56. }
  57. next()
  58. }
  59. app.get('/session', getUser, (req, res) => {
  60. // get the session id
  61. console.log('session id:', req.session.id)
  62. // the session will be automatically stored in Redis with the key prefix 'sess:'
  63. const sessionKey = `sess:${req.session.id}`;
  64. // let's see what is in there
  65. client.get(sessionKey, (err, data) => {
  66. console.log('session data in redis:', data)
  67. })
  68. res.status(200).send('OK');
  69. })


VueJS上的方法:

  1. getSession: async function () {
  2. axios({
  3. url: 'https://server.example.com/session',
  4. withCredentials: true,
  5. }).then(res => {
  6. console.log(res)
  7. })
  8. },

vd2z7a6w

vd2z7a6w1#

要使其工作,需要进行一些更改:
预检设置被设置了两次,所以在下面的代码中,我需要删除第二行:

  1. app.use(cors(corsOptions));
  2. app.options('*', cors(corsOptions)) //delete this

字符串
我试图在“// Add headers”下设置的header没有进入preflight请求,所以我需要添加“credentials:true”到corsOptions并删除“// Add headers”下的代码:

  1. var corsOptions = {
  2. origin: function (origin, callback) {
  3. if (corsWhitelist.indexOf(origin) !== -1) {
  4. callback(null, true)
  5. } else {
  6. callback(new Error('Not allowed by CORS - '+origin))
  7. }
  8. },
  9. credentials: true
  10. }


最后但并非最不重要的是,会话定义中的cookie设置不适用于跨域请求。具体来说,“sameSite:“无”和“安全:“真的”是必要的。结果如下所示:

  1. app.use(session({
  2. store: new RedisStore({ client: client }),
  3. secret: 'someSecret',
  4. resave: false,
  5. saveUninitialized: true,
  6. cookie: {
  7. secure: true,
  8. httpOnly: false,
  9. sameSite: 'none',
  10. maxAge: 1000 * 60 * 10
  11. }
  12. }))

展开查看全部
htrmnn0y

htrmnn0y2#

我也有同样的问题。我的代码只要在本地主机上运行就可以工作(客户端和Nodejs)。但是当我在服务器上推送Nodejs时,它会为每个请求创建一个新的Session。

注意:我在http上运行Nodejs,我也尝试了会话cookie设置的所有组合。

这是我的代码
服务器上的Nodejs:

  1. app.disable('x-powered-by');
  2. app.set('trust proxy', 1); // trust first proxy
  3. app.use(session({ // express-session
  4. secret: "MySecret",
  5. resave: false,
  6. saveUninitialized: false,
  7. rolling: true,
  8. cookie: {
  9. secure: false,
  10. httpOnly: false,
  11. sameSite: 'none'
  12. }
  13. }));
  14. app.use(cors({
  15. origin: 'http://localhost:3000',
  16. credentials: true
  17. }));

字符串
客户端Reactjs localhost:

  1. // First Login request creates a new session for the user
  2. const resp = await axios.post('http://my-host:8000/login', {
  3. "email": "me@none.com",
  4. "password": "hellokitty"
  5. },
  6. {
  7. withCredentials: true
  8. }
  9. );
  10. // Second request cretes new session if Nodejs is running on a remote Server
  11. const products = await axios.get("http://my-host:8000/getProducts", {
  12. withCredentials: true
  13. });

展开查看全部

相关问题