使用axios进行post请求时未收到Set-Cookie头部信息。

9
我有一个 PHP 脚本,如果直接在浏览器中(或通过 postman)调用,它可以成功返回一些简单的头部信息以及 set-cookie 头部信息。我可以像在 Chrome DevTools 中那样读取响应头部信息。但是一旦我通过 Axios 调用该脚本,set-cookie 头部信息就不会显示出来,并且浏览器里也没有保存任何 cookie。
我尝试了一些不同的方法,比如在服务器端更改响应头信息并在 axios 中使用 "withCredentials: true",但都没有起作用。 我甚至没有收到任何错误或任何与跨源资源共享相关的问题。
PHP 代码:
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST, GET");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
header("Access-Control-Max-Age: 99999999");
setcookie("TestCookie", "Testing", time() + 3600, "/", "localhost", 0);
die();

JS:

Vue.prototype.$http = axios.create({
    baseURL: XYZ,
    withCredentials: true
})

我的第一个问题是:为什么直接调用PHP脚本时,头信息会出现?如何通过axios获取头信息呢?

你确定不是由于浏览器设置阻止了第三方cookie吗?https://dev59.com/BGYq5IYBdhLWcg3wwDRA#16634941 - 04FS
嗯,我尝试直接使用同一个浏览器调用脚本,它可以正常工作。或者是axios在请求中阻止了某些内容吗?刚刚检查了你提供的链接,Chrome也没有阻止第三方cookie。 - user5242820
1
“我试着直接使用相同的浏览器调用脚本,它成功了。” - 如果你直接调用它,那么它不是第三方的... - 04FS
抱歉,刚刚更新了我的评论。我没有阻止第三方Cookie。 - user5242820
4个回答

7
可能是cookie设置了“httpOnly”,这意味着客户端的JavaScript无法读取它。因此,在Chrome的cookie部分不会显示。在Mozilla中测试同样的请求,头信息将会显示。

6
我使用axios创建了一个独立的命令行脚本,但在头部中没有收到'Set-Cookie'。使用curl发送相同的post请求会显示头部中的Set-Cookie值。Postman也能接收到Set-Cookie头部。我尝试了使用JavaScript Fetch也无法显示头部。这让我很疯狂。 - A.W.

5

这可能并不适用于你的情况,但我在使用axios时在这个独立的Node.js脚本中遇到了同样的问题。

const config = {
    url: 'https://remote.url/login',
    method: 'post',        
    headers: {
        'content-type': 'application/x-www-form-urlencoded',
    },
    data: qs.stringify({
        'email': username,
        'password': pwd
    })
}

axios(config).then(res => {
    console.log(res.headers);
}).catch(err => {
    console.log(err);
})

这个请求返回了状态码为 200 的 HTTP 响应,但头部中没有包含“set-cookie”。使用 curl 工具可以正确地检索到头部信息,但状态码却是 302。
在 axios 中添加以下配置选项后:
maxRedirects: 0,
validateStatus: function (status) {
    return status <= 302; // Reject only if the status code is greater than 302
  },

我在axios的response.header中收到了set-cookie

{
  server: 'nginx/1.16.1',
  date: 'Fri, 27 Dec 2019 16:03:16 GMT',
  'content-length': '74',
  connection: 'close',
  location: '/',
  'set-cookie': [
    'cookiename=xxxxxxxxxxxxxxxxxxxxx; path=/; expires=Sat, 26-Dec-2020 16:03:16 GMT'
  ],
  status: '302',
  'x-frame-options': 'DENY'
}

没有设置 maxRedirects: 0,我收到了远程URL主页的HTML。

没有设置 validateStatus,我在err.response.headers对象中收到了 set-cookie 头部。


1
这对我也起作用了。谢谢你。我的三个小时...maxRedirects: 0, validateStatus: function (status) { return status <= 302; // 只有当状态码大于302时才拒绝 }, - Akim Khalilov

3
在我的情况下,网络面板显示响应具有“Set-Cookie”标头,但在axios中标头不会显示,而cookie被设置了。
对我来说,解决方法是设置Access-Control-Expose-Headers标头。
解释:
从axios存储库中的问题this comment的评论中,我被引导到这个person's notes,这使我设置了Access-Control-Expose-Headers header -- 现在cookie在客户端中正确设置。
因此,在Express.js中,我必须将exposedHeaders选项添加到我的cors中间件中:
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请求中使用。

例如:

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

你好,我想知道你是否在生产环境中让它工作了。我有一个类似的React + Flask设置,本地都可以运行(可能是因为端口之间共享了cookies???),但一旦部署到生产环境中,就无法工作。 - jeff
嗯...这是一段时间以前的事情了,当时只是我的一个副业项目,所以很难记得清楚。我想我曾经部署过这些东西,但并没有在任何重要的方式下使用。不过也有可能我从来没有部署过,一直都只是本地使用。很抱歉我不能给你一个更明确的答案@TheVisionary。 - jnotelddim

1

对我来说,工作是像这样添加{withCredentials: true}:

axios
.post(url, {
    foo: foo,
    baz: baz,
    }, {withCredentials: true})
.then(.............

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接