You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Node.js中Axios发起OAuth1认证GET请求的401错误

问题:Axios发起OAuth1.0 GET请求返回401认证错误

在Node.js环境使用Axios调用预约应用的可用时段接口,Postman测试正常,但复制Postman生成的代码后触发401认证错误。

相关代码

app.get("/slots", (req, res) => {
    getAvailableSlots(res);
})
const getAvailableSlots = (res) => {
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: '<url>&oauth_consumer_key=<key>&oauth_token=<token>&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1680087781&oauth_nonce=AKuBSQsiXz1&oauth_version=1.0&oauth_signature=nRiByohboigwEbDuqr0yDzy%2BHjw%3D',
      headers: { 
        'Cookie': 'session_id=fd65f21c120061ce905241be94d10f0fd807cf48'
      }
    };
    
    axios.request(config)
    .then((response) => {
      res.send(JSON.stringify(response.data));
    })
    .catch((error) => {
      res.send(error);
    });
}

错误信息

{"message":"Request failed with status code 401","name":"AxiosError","stack":"AxiosError: Request failed with status code 401\n    at settle (/Users/admin/projects/professionals-appointment-booking-widget/node_modules/axios/dist/node/axios.cjs:1900:12)\n    at IncomingMessage.handleStreamEnd (/Users/admin/projects/professionals-appointment-booking-widget/node_modules/axios/dist/node/axios.cjs:2952:11)\n    at IncomingMessage.emit (node:events:525:35)\n    at endReadableNT (node:internal/streams/readable:1359:12)\n    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)","config":{"transitional":{"silentJSONParsing":true,"forcedJSONParsing":true,"clarifyTimeoutError":false},"adapter":["xhr","http"],"transformRequest":[null],"transformResponse":[null],"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"maxBodyLength":null,"env":{},"headers":{"Accept":"application/json, text/plain, */*","Authorization":"OAuth oauth_consumer_key=\"j5r7K9FLCRbuli9w4Z4Ddyq6pnYY1ooc\",oauth_token=\"IK4BaunTMgBRk9J9wVLsUZW4eHjPZyYY\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1680087105\",oauth_nonce=\"O5XKmWv8pS6\",oauth_version=\"1.0\",oauth_signature=\"WxrQNOA9rM7mNePuju8jGoM%2BF4Y%3D\"","Cookie":"session_id=fd65f21c120061ce905241be94d10f0fd807cf48","User-Agent":"axios/1.3.4","Accept-Encoding":"gzip, compress, deflate, br"},"method":"get","url":"https://crm.cadabams.com/restapi/1.0/object/slot.booking?domain=[(%27doctor_id%27,%20%27=%27,5314),%20(%27availability%27,%20%27=%27,%20%27open%27)]&fields=[%27doctor_id%27,%20%27start_datetime%27,%20%27stop_datetime%27,%27id%27%20]"},"code":"ERR_BAD_REQUEST","status":401}

问题分析

  1. OAuth参数重复传递:代码中URL已携带OAuth参数,但错误日志显示Headers里同时存在Authorization的OAuth头,导致认证逻辑冲突。
  2. 固定OAuth动态参数:Postman生成的oauth_timestamp和oauth_nonce是静态值,OAuth1.0要求这两个参数每次请求都动态生成(timestamp为当前时间戳,nonce为随机字符串),固定值会直接导致签名失效。
  3. Cookie环境不一致:Postman中的session_id仅适用于Postman的会话环境,Node.js请求中的Cookie可能已过期或不被服务器认可。

解决方案

1. 统一OAuth参数传递方式

移除URL中的OAuth参数,仅通过Authorization头传递认证信息,避免参数冲突:

const getAvailableSlots = (res) => {
    let config = {
      method: 'get',
      maxBodyLength: Infinity,
      url: 'https://crm.cadabams.com/restapi/1.0/object/slot.booking?domain=[(%27doctor_id%27,%20%27=%27,5314),%20(%27availability%27,%20%27=%27,%20%27open%27)]&fields=[%27doctor_id%27,%20%27start_datetime%27,%20%27stop_datetime%27,%27id%27%20]',
      headers: { 
        'Authorization': 'OAuth oauth_consumer_key="j5r7K9FLCRbuli9w4Z4Ddyq6pnYY1ooc",oauth_token="IK4BaunTMgBRk9J9wVLsUZW4eHjPZyYY",oauth_signature_method="HMAC-SHA1",oauth_timestamp="<动态时间戳>",oauth_nonce="<随机字符串>",oauth_version="1.0",oauth_signature="<动态生成的签名>"',
        'Cookie': 'session_id=<有效session_id>'
      }
    };
    
    axios.request(config)
    .then((response) => {
      res.send(JSON.stringify(response.data));
    })
    .catch((error) => {
      res.send(error);
    });
}

2. 动态生成OAuth1.0参数

手动生成参数易出错,推荐用oauth-1.0a库自动处理签名逻辑:

  • 安装依赖:npm install oauth-1.0a
  • 修改代码自动生成参数:
const OAuth = require('oauth-1.0a');
const crypto = require('crypto');

// 初始化OAuth配置
const oauth = OAuth({
  consumer: {
    key: 'j5r7K9FLCRbuli9w4Z4Ddyq6pnYY1ooc',
    secret: '<你的consumer secret>' // Postman可能隐藏该密钥,需补充
  },
  signature_method: 'HMAC-SHA1',
  hash_function(base_string, key) {
    return crypto.createHmac('sha1', key).update(base_string).digest('base64');
  }
});

// 填写token信息
const token = {
  key: 'IK4BaunTMgBRk9J9wVLsUZW4eHjPZyYY',
  secret: '<你的token secret>' // 补充对应的token密钥
};

const getAvailableSlots = (res) => {
  const url = 'https://crm.cadabams.com/restapi/1.0/object/slot.booking';
  const params = {
    domain: '[(\'doctor_id\', \'=\',5314), (\'availability\', \'=\', \'open\')]',
    fields: '[\'doctor_id\', \'start_datetime\', \'stop_datetime\',\'id\']'
  };

  // 自动生成认证头
  const authHeader = oauth.toHeader(oauth.authorize({url, method: 'GET', params}, token));

  let config = {
    method: 'get',
    url: url,
    params: params,
    headers: { 
      ...authHeader,
      'Cookie': 'session_id=<有效session_id>'
    }
  };
  
  axios.request(config)
  .then((response) => {
    res.send(JSON.stringify(response.data));
  })
  .catch((error) => {
    res.send(error);
  });
}

3. 验证Cookie有效性

  • 检查session_id是否在Node.js请求环境中有效,可通过浏览器访问目标接口,提取当前有效的session_id替换。
  • 若接口允许,可尝试移除Cookie,确认是否仅依赖OAuth认证即可访问。

内容的提问来源于stack exchange,提问作者rehan.ankalgi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:27:36