未设置Set-Cookie标头中的Cookie

时间:2020-05-02 05:55:11

标签: node.js reactjs cookies axios cross-domain

我正在使用axios从reactjs客户端向node.js服务器发送请求,如下所示。

import axios from 'axios';

const apiClient = axios.create({
  withCredentials: true,
  baseURL: 'http://localhost:8080'
});

async function(payload) {
  try {
    debugger;
    let result = await apiClient.post('/auth/signup/', payload);
    debugger;
    return result;
  } catch (error) {
    debugger;
    throw error;
  }
}

node.js端点在响应中设置一个cookie,如下所示。

const express = require('express');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser')
const cors = require('cors');
const jwt = require('jsonwebtoken');

router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: true }));
router.use(cors({ origin: 'http://localhost:3000', credentials: true, exposedHeaders: ['Set-Cookie', 'Date', 'ETag']} ));
router.use(cookieParser());


router.post('/signup', async (req, res, next) => {
  debugger;
  let database = req.app.locals.database;
  try {
    let user = await database.findByUsername(req.body.username);
    let token = await jwt.sign({username: user.username}, config.secret, {expiresIn: "15m"});
    res.cookie('jwt',  token, {
      maxAge: 900,
    });
  } catch (error) {
    debugger;
    return res.status(503).send({ auth: false, message: 'Database error.' });
  }
});

响应的Set-Cookie标头包含预期的cookie。

Set-Cookie Header

但是,Chrome似乎没有设置cookie,因为在开发人员控制台的“应用程序”窗口中看不到cookie。

Cookies

我已经查看了以下问题的答案,其中提到在axios配置中设置{ withCredentials: true },并且在node.js中未对cors使用通配符起源,但是我已经做到了。

Set-Cookie header not setting cookie in Chrome

Set cookies for cross origin requests

关于为什么未设置cookie以及如何解决此问题的任何想法?

2 个答案:

答案 0 :(得分:1)

尽管您将客户端和服务器托管在与http://localhost相同的域中,但是端口是不同的,因此此处同源策略失败。您可以检查https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy

这样,您发出CORS请求,请在当前浏览器的开发人员工具中检查“网络”标签,在客户端向服务器发送OPTIONS请求之前,您可能会看到预检请求POST

服务器必须指定标头以接受下一个请求的源-使用方法http://localhost:8000来自POST的POST请求,您可以引用https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

HTTP/1.1 204 No Content
Connection: keep-alive
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: POST // Your next request will use POST method
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials: true // cookies accepted

已添加:

Set-Cookie中,Max-Age必须为non-zero digit。根据{{​​3}}将其四舍五入为整数。对于express.js,cookies的maxAge属性的大小为RFC doc

解决方案将maxAge属性设置为second * 1000

    res.cookie('jwt',  token, {
      maxAge: 10000,
    });

答案 1 :(得分:0)

这是我对类似问题https://stackoverflow.com/a/62821342/8479303

的回答的转贴

在我的情况下,网络面板显示响应具有“ Set-Cookie”标头,但是在axios中,标头不会显示,并且正在设置cookie。

对我来说,解决方法是设置Access-Control-Expose-Headers标头。

为进行解释,从this comment到axios存储库中的一个问题,我被定向到这个person's notes,这导致我设置了Access-Control-Expose-Headers header -现在cookie已正确设置在客户。

因此,在Express.js中,我不得不在我的cors中间件中添加exposedHeaders选项:

const corsOptions = {
  //To allow requests from client
  origin: [
    "http://localhost:3001",
    "http://127.0.0.1",
    "http://104.142.122.231",
  ],
  credentials: true,
  exposedHeaders: ["set-cookie"],
};

...

app.use("/", cors(corsOptions), router);

同样重要的是,在axios端,我使用withCredentials配置来跟踪我想包含cookie的axios请求。

ex /

const { data } = await api.get("/workouts", { withCredentials: true });