使用 React Axios POST 请求时未设置 Express Session Cookie

Posted

技术标签:

【中文标题】使用 React Axios POST 请求时未设置 Express Session Cookie【英文标题】:Express Session Cookie Not Being Set when using React Axios POST Request 【发布时间】:2020-11-24 20:12:57 【问题描述】:

设置

我已经使用 create-react-app 设置了一个前端环境。在这种环境中,我使用 Axios 向我的 Node JS Express 后端服务器 /login 端点发出 POST 请求。我使用 express-sessions 设置会话中间件并将会话存储在 Redis 中。我目前在 localhost 中运行所有这些。

环境

React App - http://localhost:3005/kp(注意:服务运行在 http://localhost:3005 但是,所有路由都包含/kp)

Express 后端 - http://localhost:5001

Redis - http://localhost:6379

什么有效

当前端将请求发送到后端时,Express 服务器会执行此操作并对用户进行身份验证;它将用户名存储在 req.session.username 中(这只是作为测试),Redis 控制台显示键值存储成功,前端网络选项卡显示 200 状态,带有 Set-Cookie 响应标头和一个选项卡显示 cookie(下面的屏幕截图)。

问题

似乎一切正常,但浏览器中未设置 cookie。我刷新了页面,再次尝试了很多次,但它不会在任何浏览器(谷歌浏览器和 Safari)中设置 cookie。我感到很沮丧,因为 Chrome 似乎承认存在 Set-Cookie,但由于某种原因忽略了它。

我的尝试

Axios

    我已尝试设置 withCredentials: true - 不起作用 验证带有 Set-Cookie 的 cookie 在 POST 请求后被发送回前端

后台

    我已经检查了我的 CORS 策略,但它们看起来还不错;但是,我对 CORS 不是很好,所以那里可能存在配置错误 尝试在 CORS 策略中将凭据设置为 true 已验证正在使用 Redis 设置带有变量的会话。

代码

React 前端 Axios POST 请求

      axios.post('http://localhost:5001/login', loginBody, 
        headers: 
          'Content-Type': 'application/json'
        
      ,
         withCredentials: true 
      )
        .then((res) => 
          console.log(res);
        )
        .catch((error) => 
          console.log(error);
          this.setState(
            errorMessage: `Server Error`,
            loading: false
          );
        );

快递服务器

const express = require('express');
const http = require('http');
const cors = require('cors');
const socketServer = require('./src/sockets');
const bodyParser = require('body-parser');
const session = require('express-session');
const redis = require('redis');
const redisClient = redis.createClient();
const redisStore = require('connect-redis')(session);
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
const port = process.env.PORT || 5001;
const  loginRoutes  = require('./src/routers');
const app = express();

redisClient.on('error', (err) => 
  console.log('Redis error: ', err);
);

app.use(cors(
  origin: '*',
  methods: ['POST', 'PUT', 'GET', 'OPTIONS', 'HEAD'],
  credentials: true
));

// Redis session storage setup
// API Docs for express-session: https://www.npmjs.com/package/express-session
const sessionMiddleware = session(
  secret: process.env.REDIS_SECRET || 'testing12345',
  name: 'session',
  resave: false,
  saveUninitialized: true,
  cookie: 
    secure: false
  ,
  store: new redisStore(
    
      host: process.env.REDIS_HOSTNAME,
      port: process.env.REDIS_PORT,
      client: redisClient,
      ttl: 604800
    
  )
);

// Uses session middleware
app.use(sessionMiddleware);

app.use(bodyParser.json( limit: '5mb' ));

const server = http.createServer(app);

// Starts Socket Server
socketServer(server, sessionMiddleware);

// Uses the routes from the router directory
app.use(loginRoutes);

server.listen(port, () => 
  console.log(`Listening on port: $port`);
);

截图

网络响应

请求 Cookie

应用程序 Cookie

如您所见,浏览器 cookie 列表中缺少该 cookie。我有一种感觉,它很小,但我找不到任何东西。

我在任何服务中都没有收到任何错误。提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

解决方案

正如 Michał Lach 指出的那样,我在 Axios 调用中将 withCredentials 放在了错误的位置。

前端 Axios

  axios.post('http://localhost:5001/login', loginBody, 
    headers: 
      'Content-Type': 'application/json'
    ,
    withCredentials: true
  )

但是,一旦我这样做了,我就开始出现 CORS 错误。 CORS 错误是您的 Access-Control-Allow-Origin (origin) 配置中不能有通配符“*”。对于这个例子,我将其更改为仅指向 http://localhost:3005;但是,有一些方法可以执行此处记录的动态白名单:https://www.npmjs.com/package/cors#configuring-cors-w-dynamic-origin

后台

app.use(cors(
  origin: 'http://localhost:3005',
  methods: ['POST', 'PUT', 'GET', 'OPTIONS', 'HEAD'],
  credentials: true
));

一旦我进行了这些更改,cookie 就会开始在前端正确设置。

【讨论】:

【参考方案2】:

您确定,您正确设置了 axios 选项吗?

你有:

    axios.post('http://localhost:5001/login', loginBody, 
    headers: 
      'Content-Type': 'application/json'
    
  ,
     withCredentials: true 
  )
    .then((res) => 
      console.log(res);
    )
    .catch((error) => 
      console.log(error);
      this.setState(
        errorMessage: `Server Error`,
        loading: false
      );
    );

试试这个:

    axios.post('http://localhost:5001/login', loginBody, 
    headers: 
      'Content-Type': 'application/json'
    ,
     withCredentials: true 
  
        ....

【讨论】:

非常感谢您的帮助。我完全错过了这个。虽然这并没有回答我的问题,但它确实让我得到了正确的答案,这个答案有点复杂,因为它也与 CORS 有关。我会发布一个解释。

以上是关于使用 React Axios POST 请求时未设置 Express Session Cookie的主要内容,如果未能解决你的问题,请参考以下文章

如何使用自定义 React 钩子通过 Axios 发出 POST 或 DELETE 请求

使用 Axios Post 时未找到购物车会话

无法使用来自 react/axios 的 JSON 发出 POST 请求以恢复服务器

无法从 axios POST 请求中获得响应(React)

React js 和 axios POST 请求发送空数组

axios.post 返回 400 React Native 的错误请求