在 React Native 中使用带有 Fetch 的授权标头

IT技术 javascript oauth-2.0 react-native fetch-api
2021-02-02 14:33:23

我正在尝试fetch在 React Native 中使用从 Product Hunt API 中获取信息。我已经获得了正确的访问令牌并将其保存到 State,但似乎无法在 GET 请求的 Authorization 标头中传递它。

这是我到目前为止所拥有的:

var Products = React.createClass({
  getInitialState: function() {
    return {
      clientToken: false,
      loaded: false
    }
  },
  componentWillMount: function () {
    fetch(api.token.link, api.token.object)
      .then((response) => response.json())
      .then((responseData) => {
          console.log(responseData);
        this.setState({
          clientToken: responseData.access_token,
        });
      })
      .then(() => {
        this.getPosts();
      })
      .done();
  },
  getPosts: function() {
    var obj = {
      link: 'https://api.producthunt.com/v1/posts',
      object: {
        method: 'GET',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + this.state.clientToken,
          'Host': 'api.producthunt.com'
        }
      }
    }
    fetch(api.posts.link, obj)
      .then((response) => response.json())
      .then((responseData) => {
        console.log(responseData);
      })
      .done();
  },

我对我的代码的期望如下:

  1. 首先,我将fetch使用导入的 API module中的数据获取访问令牌
  2. 之后,我会将 的clientToken属性设置this.state为等于收到的访问令牌。
  3. 然后,我将运行getPosts它应该返回一个包含来自 Product Hunt 的当前帖子数组的响应。

我能够验证是否正在接收访问令牌并将this.state其作为其clientToken财产接收我还能够验证getPosts正在运行。

我收到的错误如下:

{"error":"unauthorized_oauth", "error_description":"请提供有效的访问令牌。有关如何授权 api 请求,请参阅我们的 api 文档。另请确保您需要正确的范围。例如 \"private public\ " 用于访问私有端点。"}

我一直在假设我没有在我的授权标头中正确传递访问令牌,但似乎无法弄清楚确切原因。

4个回答

使用授权标头获取示例:

fetch('URL_GOES_HERE', { 
   method: 'post', 
   headers: new Headers({
     'Authorization': 'Basic '+btoa('username:password'), 
     'Content-Type': 'application/x-www-form-urlencoded'
   }), 
   body: 'A=1&B=2'
 });
2021-03-16 14:33:23
api 端点没有启用 CORS,所以这可能是它对我不起作用的原因。谢谢。我最终为 Firefox 安装了“cors无处不在”附加组件,并且它奏效了。
2021-03-18 14:33:23
这对我不起作用。'Authorization'头默默未能按萤火虫重视。我什至尝试包含credentials: 'include'在可选对象中。
2021-03-31 14:33:23
@RonRoyston 你在看 OPTIONS 电话吗?如果 API 端点没有启用 CORS(Access-Control-Allow-Origin: * 如果从不同的域访问),那么它可能会在 OPTIONS 调用中失败。
2021-04-07 14:33:23
关于@RonRoyston 看到的问题,您需要导入 btoa 库,该不是node.js原生的。(它是浏览器库的一个端口。)否则 auth 头创建会默默地失败。我们正在经历同样的事情。
2021-04-07 14:33:23

事实证明,我fetch错误地使用了该方法。

fetch 需要两个参数:API 的端点,以及可以包含正文和标头的可选对象。

我将预期的对象包装在第二个对象中,这没有得到任何想要的结果。

这是它在高层次上的样子:

fetch('API_ENDPOINT', OBJECT)  
  .then(function(res) {
    return res.json();
   })
  .then(function(resJson) {
    return resJson;
   })

我这样构造我的对象:

var obj = {  
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'Origin': '',
    'Host': 'api.producthunt.com'
  },
  body: JSON.stringify({
    'client_id': '(API KEY)',
    'client_secret': '(API SECRET)',
    'grant_type': 'client_credentials'
  })
}
哦,我一直在用那个例子访问你的个人网站!这就是我第一次模拟我的方式。不过我发现了我的问题,只是我的网址错误。/最后需要一个我失踪的......
2021-03-26 14:33:23
谢谢,这很有帮助。值得注意的是,虽然 fetch 文档指出 fetch 不处理 cookie,但您也可以使用此代码手动将 cookie 添加到标头。只需保存 uid 和密钥并执行以下操作: var obj = { method: 'GET', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Cookie': 'uid='+uid+'; 键='+键 });
2021-03-31 14:33:23
完成了,希望有帮助
2021-04-03 14:33:23
你能不能提供现在工作的代码?我正在尝试将 fetch 与授权标头一起使用,但我认为我的身份验证代码不会作为标头传递,因为我收到了401响应。
2021-04-07 14:33:23

我遇到了同样的问题,我使用 django-rest-knox 作为身份验证令牌。事实证明,我的 fetch 方法没有问题,它看起来像这样:

...
    let headers = {"Content-Type": "application/json"};
    if (token) {
      headers["Authorization"] = `Token ${token}`;
    }
    return fetch("/api/instruments/", {headers,})
      .then(res => {
...

我正在运行 apache。

为我解决这个问题的是更改WSGIPassAuthorization'On'in wsgi.conf

我在 AWS EC2 上部署了一个 Django 应用程序,我使用 Elastic Beanstalk 来管理我的应用程序,因此在django.config.

container_commands:
  01wsgipass:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'
django.config 它在项目中还是在 apache 配置中?
2021-03-25 14:33:23
completed = (id) => {
    var details = {
        'id': id,

    };

    var formBody = [];
    for (var property in details) {
        var encodedKey = encodeURIComponent(property);
        var encodedValue = encodeURIComponent(details[property]);
        formBody.push(encodedKey + "=" + encodedValue);
    }
    formBody = formBody.join("&");

    fetch(markcompleted, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: formBody
    })
        .then((response) => response.json())
        .then((responseJson) => {
            console.log(responseJson, 'res JSON');
            if (responseJson.status == "success") {
                console.log(this.state);
                alert("your todolist is completed!!");
            }
        })
        .catch((error) => {
            console.error(error);
        });
};