即使使用 withCredential: true,axios 也无法发送带有请求的 cookie

Posted

技术标签:

【中文标题】即使使用 withCredential: true,axios 也无法发送带有请求的 cookie【英文标题】:axios cannot send cookie with request even with withCredential: true 【发布时间】:2019-03-31 20:27:37 【问题描述】:

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

    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();
);

和客户端的 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);
   )

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

【问题讨论】:

您是在设置 cookie 服务器端还是客户端?您需要确保未使用 http-only 标志设置 cookie。如果您打开 chrome 开发人员工具并转到“应用程序”然后转到“Cookies”并检查 HTTP 列中是否有复选 (✓) 图标,则可以检查他们是否有此标志。 @RalphNajm 哦,实际上我的错误是将其设置为不仅仅是 http。谢谢,现在可以使用了 欢迎您:) 【参考方案1】:

我发现我的错误。将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);
   )

我仍然想问为什么此更改会有所帮助,因此我们将不胜感激

【讨论】:

【参考方案2】:

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

client/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;

client/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))
)

那么对于您的 API,您可以在定义 express 中间件的任何位置使用 cors,而不是指定 CORS 标头:

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

app.use(
  cors(
    credentials: true,
    origin
  ),
);

【讨论】:

【参考方案3】:
axios.post('http://localhost:5000/api/auth/login', userEmail, userPassword ,
        withCredentials: true,
      )


const cors = require("cors");
expressApplication.use(cors(
 origin: ["http://localhost:2000", "http://localhost:3000"],
 credentials: true
));

【讨论】:

【参考方案4】:

我发现这篇文章很有帮助:https://medium.com/acmvit/handling-cookies-with-axios-872790241a9b

但可能取决于服务器设置。

在客户端设置 Axios 标头:

headers: Authorization: `Bearer $cookie_value`,
withCredentials: true,
crossDomain: true

【讨论】:

【参考方案5】:

现在 2020 年,Chrome 对跨域 cookie 设置添加了更多烦人的限制,您必须将带有 SameSite 的 cookie 设置为 none,否则 Chrome 将拒绝发送 cookie。更多,如果你设置了SameSite,你必须设置secure

下面是一个例子,说明如何在 nginx 中设置这个更改,它可能不适合你的情况,但供参考。

proxy_cookie_path / "/; secure; SameSite=none";

【讨论】:

以上是关于即使使用 withCredential: true,axios 也无法发送带有请求的 cookie的主要内容,如果未能解决你的问题,请参考以下文章

Internet Explorer 10 忽略 XMLHttpRequest 'xhr.withCredentials = true'

在 Firefox 的 jQuery $ajax 调用中使用 xhrFields: withCredentials: true 时的状态码 = 0

OkHttp POST 请求设置 withCredentials 为 True?

尽管 withCredentials:true 未能在 GET 请求中发送 Cookie

如何将withCredentials = true添加到Jquery .load()?

为 withCredentials 指定 CORS 标头:true