在React Native中将授权标头与Fetch一起使用


141

我试图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模块中的数据访问令牌
  2. 之后,我将设置clientToken属性this.state等于接收到的访问令牌。
  3. 然后,我将运行getPosts它将返回一个响应,其中包含来自Product Hunt的一系列当前帖子。

我能够验证是否已接收到访问令牌并将this.state其作为其clientToken属性接收。我也可以验证它getPosts是否正在运行。

我收到的错误如下:

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

我一直在进行以下假设:我不知道如何在授权标头中正确传递访问令牌,但似乎无法弄清楚原因。


2
正如本SO中所指出的,标头旨在为小写(一些服务器尊重这一点,而其他服务器则不这样做。)我之所以分享是因为我不了解自己而被它咬住了(浪费了尝试调试问题的时间。)不幸的是,如此多的项目,示例和文章似乎并不尊重这一点。
tj

@tj标头名称不区分大小写,而这正是您所链接问题上公认的+最佳答案的意思。
coreyward

Answers:


195

使用授权标头获取示例:

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'
 });

4
这对我不起作用。该'Authorization'头默默未能按萤火虫重视。我什至尝试将其包含credentials: 'include'在可选对象中。
罗尼·罗斯顿

7
@RonRoyston您在看OPTIONS电话吗?如果API端点未启用CORS(Access-Control-Allow-Origin:*,如果从其他域进行访问),则它可能在OPTIONS调用中失败。
科迪莫妮兹

1
api端点未启用CORS,因此这可能就是为什么它不适用于我的原因。谢谢。我最终为Firefox安装了“随处可见的CORS”附加组件,它可以正常工作。
罗尼·罗伊斯顿

3
回到@RonRoyston看到的问题,您需要导入btoa库,该不是node的本机。(这是浏览器lib的端口。)否则,auth标头的创建会静默失败。我们正在经历同样的事情。
Freewalker


67

事实证明,我使用的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'
  })

您能否提供现在可以使用的代码?我试图将fetch与授权标头一起使用,但我不认为我的身份验证代码作为标头传递,因为我得到了401响应。
GoldenBeet15年

2
完成,希望对您有所帮助
Richard Kho 2015年

1
哦,我曾经在您的个人网站上刊登过该示例!这就是我第一次建模的方式。我发现了我的问题,只是我的网址错误。/最后我想念它需要一个...
GoldenBeet 2015年

1
谢谢,这很有帮助。值得一提的是,虽然访存文档指出访存不处理Cookie,但您也可以使用此代码将Cookie手动添加到标头中。只需保存uid和key并执行类似的操作:var obj = {method:'GET',headers:{'Accept':'application / json','Content-Type':'application / json','Cookie': 'uid ='+ uid +'; key ='+ key});
达斯汀

8

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

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

我正在跑步阿帕奇。

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

我在AWS EC2上部署了Django应用程序,并使用Elastic Beanstalk管理我的应用程序,因此在中django.config,我这样做:

container_commands:
  01wsgipass:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'

0
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);
        });
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.