使用 http get req 从 JS 到 SlackAPI 时,预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权

发布于 2025-01-10 15:47:10 字数 2695 浏览 0 评论 0原文

我知道有很多类似的问题,但我发布这个是因为我觉得它略有不同。

我正在尝试使用 HTTP 请求向 Slack API 发送 GET 请求。 具体来说,代码如下所示。

import useSWR from "swr";

const useSlackSearch = (query: string) => {
  const token = process.env.NEXT_PUBLIC_SLACK_API_USER_TOKEN;
  const myHeaders = new Headers();
  myHeaders.append("Authorization", "Bearer " + token);

  const slackURL = `https://slack.com/api/search.messages?query=${query}`;

  const fetcher = async (url: string) => {
    const response = await fetch(url, {
      headers: myHeaders,
    }).then((res) => res.json());
    return response;
  };

  const { data, error } = useSWR(slackURL, fetcher, {
    revalidateOnFocus: true,
    revalidateOnReconnect: true,
  });

  if (error) {
    return console.log(`Failed to load: ${error}`);
  } else if (!data) {
    return console.log("Loading...");
  } else {
    console.log(data);
    return data;
  }
};

export default useSlackSearch;

我使用的环境如下。

阅读下面的 MDN 文章后,我了解到

  • MDN 定义了一种简单的 HTTP 请求,
  • 如果您要发送的请求不存在对应于这个简单的请求,浏览器将发送一个预检请求,
  • 在该预检请求的响应中,有一个名为 Access-Control-Allow-Headers 的标头。
  • 只有设置为此 Access-Control-Allow-Headers 标头值的标头才能在预检后用作主请求中的标头。
  • 在这种情况下,我尝试使用 Authorization 标头,但它受到上述限制的限制。

https://developer.mozilla.org/en-US/文档/Web/HTTP/CORS#simple_requests https://developer.mozilla.org/en-US/docs/Glossary/ Preflight_request

这就是我所理解的。 然而,在相关方法的官方 Slack API 页面上,它说要在授权标头中指定令牌,所以我遇到了麻烦。

我也不明白如何在预检标头中指定 Access-Control-Request-Headers,如另一个提问者的线程中所述。原因是,在这种情况下,与 Slack API 通信的唯一东西是浏览器,唯一相关的源是 JavaScript(准确地说是 React / Next.js)!


之后,我发现 Slack API 的预检响应如下;

access-control-allow-headers: slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid, x-b3-sampled, x-b3-flags

正如我所想,我明白授权是不允许的,因为它不包含在值中。所以问题是如何解决。


,我后来发现来自浏览器的预检请求正确地声明了它想要使用 Authorization 作为实际的请求标头。但是,预检响应不包含该值。

输入图片此处描述

I understand that there are many similar questions, but I am posting this because I feel it is slightly different.

I am trying to send a GET request to the Slack API using an HTTP request.
Specifically, the code looks like the following.

import useSWR from "swr";

const useSlackSearch = (query: string) => {
  const token = process.env.NEXT_PUBLIC_SLACK_API_USER_TOKEN;
  const myHeaders = new Headers();
  myHeaders.append("Authorization", "Bearer " + token);

  const slackURL = `https://slack.com/api/search.messages?query=${query}`;

  const fetcher = async (url: string) => {
    const response = await fetch(url, {
      headers: myHeaders,
    }).then((res) => res.json());
    return response;
  };

  const { data, error } = useSWR(slackURL, fetcher, {
    revalidateOnFocus: true,
    revalidateOnReconnect: true,
  });

  if (error) {
    return console.log(`Failed to load: ${error}`);
  } else if (!data) {
    return console.log("Loading...");
  } else {
    console.log(data);
    return data;
  }
};

export default useSlackSearch;

The environments I'm using are as follows.

After reading the MDN articles like below, I understood that

  • There is such a thing as a simple HTTP request as defined by MDN
  • If the request you want to send does not correspond to this simple request, the browser will send a preflight request
  • In the response to that preflight request, there is a header called Access-Control-Allow-Headers.
  • Only headers set to the value of this Access-Control-Allow-Headers header can be used as headers in the main request after preflighting.
  • In this case, I tried to use the Authorization header, but it was trapped by the above restriction.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests
https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

That's all I understand.
However, on the official Slack API page for the method in question, it says to specify the token in the Authorization header, so I'm having trouble.

I also don't understand how to specify the Access-Control-Request-Headers in the preflight header, as described in another questioner's thread. The reason is that the only thing that communicates to the Slack API is the browser in this case, and the only relevant source is JavaScript (React / Next.js to be exact)!


After that, I found preflight response from Slack API as follows;

access-control-allow-headers: slack-route, x-slack-version-ts, x-b3-traceid, x-b3-spanid, x-b3-parentspanid, x-b3-sampled, x-b3-flags

As I thought, I understand that Authorization is not allowed because it is not included as a value. So the question is how to solve it.

enter image description here


Furthermore, I found out later that the preflight request from the browser properly declared that it wanted to use Authorization as an actual request header. However, the preflight response did not contain the value.

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不知所踪 2025-01-17 15:47:11

按照CBroe的建议,我能够直接联系Slack帮助中心,所以我问了这个问题。 结果我发现,截至2022年2月,浏览器的HTTP请求不受支持。当然,他们已经收到了相当多的相关请求,因此他们希望能够解决它在某个时刻。

这次,浏览器在预检请求中发送了 Access-Control-Request-Headers:Authorization。但 Slack API 服务器端不允许浏览器请求中包含 Authorization 标头。因此,Slack API 端的预检响应中的 Access-Control-Allow-Headers 中未设置授权。

因此,Slack API 端的响应返回了 Invalid Auth,即使在从浏览器发出实际请求时将 Authorization 添加为标头。

通过这个错误,让我对CORS、preflighting等HTTP请求有了更深入的了解,但由于Slack官方网站上没有明确写到,所以就留在这里了。

Following CBroe's advice, I was able to contact the Slack help center directly, so I asked this problem. What I found out as a result is that HTTP requests from browsers are not supported as of the end of February 2022. Of course, they have received quite a lot of requests regarding this, so they hope to address it at some point.

This time, the browser sent Access-Control-Request-Headers:Authorization in the preflight request. But the Slack API server side did not allow the Authorization header in the request from the browser. Therefore, Authorization was not set in the Access-Control-Allow-Headers in the preflight response from the Slack API side.

As a result, the response from the Slack API side returned Invalid Auth, even though Authorization was added as a header when making an actual request from the browser.

Through this error, I gained a deeper understanding of HTTP requests such as CORS and preflighting, but since it is not explicitly written on the official Slack website, I left it here.

忱杏 2025-01-17 15:47:11

在请求正文中使用 token 而不是 Authorization 标头对我有用。

axios({
  method: 'post',
  url: 'https://slack.com/api/chat.postMessage',
  data: `text=Hi&channel=D048GGYTJUK&token=${process.env.TOKEN}`
})

using token in request body instead of Authorization header worked for me.

axios({
  method: 'post',
  url: 'https://slack.com/api/chat.postMessage',
  data: `text=Hi&channel=D048GGYTJUK&token=${process.env.TOKEN}`
})
德意的啸 2025-01-17 15:47:11

我也无法让授权标头正常工作。但是,Slack 提供了 此示例用于在弃用查询参数方法后向 Post 正文添加令牌身份验证。
这对我来说很有效,可以从浏览器对 Slack 进行 Web API 调用(用于测试),以便 Slack 读取令牌进行身份验证。请注意,根据 Slack 的 最佳实践为了安全,用户和机器人令牌应小心存储,不要在客户端 Javascript 中使用:


    try {
      const res = await fetch("https://slack.com/api/conversations.list", {
        method: "POST",
        body: `token=${TOKEN}`, // body data type must match "Content-Type" header
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
      }).catch((error) => {
        console.log(error);
      });
      if (!res.ok) {
        throw new Error(`Server error ${res.status}`);
      } else {
        const data = await res.json();
        console.log(data);
      }
    } catch (error) {
      console.log(error);
    }

I could not get the Authorization header to work either. However, Slack provided this example for adding token authentication to the Post body following the deprecation of the query parameters method.
This worked for me to make Web API calls to Slack from the browser (for testing) so that Slack would read the token for authentication. Note, according to Slack's best practices for security, user and bot tokens should be stored with care and not used in client-side Javascript:


    try {
      const res = await fetch("https://slack.com/api/conversations.list", {
        method: "POST",
        body: `token=${TOKEN}`, // body data type must match "Content-Type" header
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
      }).catch((error) => {
        console.log(error);
      });
      if (!res.ok) {
        throw new Error(`Server error ${res.status}`);
      } else {
        const data = await res.json();
        console.log(data);
      }
    } catch (error) {
      console.log(error);
    }

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文