即使使用 withCredential: true,axios 也无法通过请求发送 cookie

Huy*_*yen 5 cookies node.js cors reactjs axios

我已经在这样的服务器上设置了

    app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.header(
    'Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization,  X-PINGOTHER'
  );
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS');
  next();
});
Run Code Online (Sandbox Code Playgroud)

和客户端的 axios (react) 像这样

axios.defaults.withCredentials = true;
axios('http://127.0.0.1:3001/orders', {
  method: 'GET',
  withCredentials: true
}).then(res => {
     console.log(res);
   }).catch(err => {
     console.log(err.response);
   })
Run Code Online (Sandbox Code Playgroud)

当我用 Postman 测试并直接输入 chrome 时,一切正常。知道我的代码有什么问题吗?

Mat*_*tta 7

如果你打算多次使用这个,那么只需创建一个 axios 配置:

客户端/src/utils/axiosConfig.js

import axios from 'axios';

const baseURL = process.env.NODE_ENV === "development"
  ? "http://localhost:3001/"
  : "http://example.com"

const app = axios.create({
    baseURL,
    withCredentials: true
})

/* 
  The below is required if you want your API to return 
  server message errors. Otherwise, you'll just get 
  generic status errors.

  If you use the interceptor below, then make sure you 
  return an "err" (or whatever you decide to name it) message 
  from your express route: 
  
  res.status(404).json({ err: "You are not authorized to do that." })

*/
app.interceptors.response.use(
  response => (response), 
  error => (Promise.reject(error.response.data.err))
)

export default app;
Run Code Online (Sandbox Code Playgroud)

客户端/src/actions/exampleAction.js

import app from '../utils/axiosConfig';

export const exampleAction = () => (
  app.get('orders') // this will be defined as baseURL + "orders" (http://localhost:3001/orders)
    .then(res => console.log(res))
    .catch(err => console.log(err))
)
Run Code Online (Sandbox Code Playgroud)

然后对于您的 API,无需指定 CORS 标头,您只需在定义中间件的任何位置使用corsexpress

const cors = require('cors');
const origin = process.env.NODE_ENV === "development" 
  ? "http://localhost:3000" 
  : "http://example.com"

app.use(
  cors({
    credentials: true,
    origin
  }),
);
Run Code Online (Sandbox Code Playgroud)


Huy*_*yen 6

我明白了我的错误。将 axios 代码更改为

axios.defaults.withCredentials = true;
axios('http://localhost:3001/orders', {
  method: 'GET',
  withCredentials: true
}).then(res => {
     console.log(res);
   }).catch(err => {
     console.log(err.response);
   })
Run Code Online (Sandbox Code Playgroud)

我仍然想问为什么这个改变有帮助,所以任何答案将不胜感激


Zha*_*uzz 5

现在 2020 年,Chrome 对跨域 cookie 设置添加了更多恼人的限制,您必须使用SameSiteto设置 cookie none,否则 Chrome 将拒绝发送 cookie。另外,如果设置了 SameSite,则必须设置secure.

以下是如何在 nginx 中设置此更改的示例,它可能不适用于您的情况,但仅供参考。

proxy_cookie_path / "/; secure; SameSite=none";
Run Code Online (Sandbox Code Playgroud)


小智 5

同样的问题,我修复了它。遵循代码:

后端

const corsConfig = {
  origin: true,
  credentials: true,
};

app.use(cors(corsConfig));
app.options('*', cors(corsConfig))
Run Code Online (Sandbox Code Playgroud)

前端

axios.defaults.withCredentials = true;
Run Code Online (Sandbox Code Playgroud)