前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >V3手动鉴权失败之Nodejs篇

V3手动鉴权失败之Nodejs篇

原创
作者头像
周朋伟
修改2020-12-11 15:49:10
2.2K0
修改2020-12-11 15:49:10
举报
文章被收录于专栏:腾讯云大数据与AI专家服务

导语

该系列其他篇章:

V3手动鉴权失败之Go篇

V3手动鉴权失败之Python篇

V3手动鉴权失败之Java篇

V3手动鉴权失败之PHP篇

V3手动鉴权失败之C#篇

腾讯云 API 全新升级 3.0 ,该版本进行了性能优化且全地域部署、支持就近和按地域接入、访问时延下降显著,接口描述更加详细、错误码描述更加全面、SDK增加接口级注释,让您更加方便快捷的使用腾讯云产品。人脸识别文字识别语音识别等众多产品均已接入云API 3.0。

腾讯云API为了更好的让用户接入,已经封装好了多种语言的SDK,只需用户传入SecrectId、SectectKey以及接口入参,即可完成接口鉴权和请求发送,具体包括Python SDKJava SDKPHP SDKGo SDKNodeJS SDK.NET SDK

案例背景

在某些情况,用户需要实现手动接口鉴权,虽然官网文档已有详细的接口鉴权流程,但是由于:

1.V3手动鉴权步骤较为复杂;

2.官网某些demo代码无法直接下载运行,仍需简单调整;

3.官网文档的demo代码覆盖面有限,没有包括全量上述六类后端语言;

基于此,很多用户只能自己尝试手动鉴权,但都返回“鉴权失败”,从而无法调通接口。

原因分析

从宏观上看,“鉴权失败”要关注两个阶段:

1. 整体的接口鉴权是否正确;

2. 模拟的鉴权请求的发送是否正确;

从历史问题回顾,有客户曾经出现接口鉴权时而成功,时而失败的情况,排查了整体的鉴权过程,完全正确,但是也的确复现了客户的问题。后来发现,用户在鉴权完成后,发送具体的请求时,传入的时间戳timestamp没有实时更新导致了报错。

解决方案

为了帮助客户更简单、更快捷地完成接口手动鉴权,并成功发送鉴权请求,将通过一系列文章专门讲解各个后端语言的手动鉴权&发送请求的可执行demo代码,助力客户快速接入。

本期将以调用人脸识别的DetectFace接口为例,详叙Nodejs语言demo。

前期准备

node环境:直接在node官网根据操作系统类型下载并安装指定安装包即可。

SecrectId和SecretKey:接口鉴权的密钥。可以把SecretId理解成“账号”,把SecretKey理解成“密码”。在自己的腾讯云官网控制台获取:访问管理 -> 访问密钥 -> API密钥管理

手动鉴权相关文档:请求结构公共参数V3接口鉴权

具体代码

为了模拟具体的http请求,需要安装request包:

代码语言:javascript
复制
npm i request

运行nodejs代码,可以完成v3鉴权,并发送http请求,收到具体的response响应。运行指令为:

代码语言:javascript
复制
node nodev3.js

具体的nodev3js代码如下,只需要简单复制,然后输入自己的SecretId和SecretKey两个字段即可:

代码语言:javascript
复制
  // 本示例为V3接口鉴权之Node.js篇,以POST请求GeneralBasicOCR接口为例
  // GET 请求的请求包大小不得超过 32KB。
  // POST 请求使用签名方法为 HmacSHA1、HmacSHA256 时不得超过1MB 。
  // POST 请求使用签名方法为 TC3-HMAC-SHA256 时支持 10MB。 这里使用 POST 示例 。 

  /**
   * 详细文档需要参考 :
   * 1. 请求结构:https://cloud.tencent.com/document/product/866/33517
   * 2. 公共参数:https://cloud.tencent.com/document/product/866/33518
   * 3. 接口鉴权v3:https://cloud.tencent.com/document/product/866/33519
   * 4. 文字识别产品介绍文档:https://cloud.tencent.com/document/product/866/37490
   */

  const crypto = require('crypto')
  var request = require("request")

  var SecretId = ""; // // SecretId, 需要替换为自己的
  var SecretKey = ""; // SecretKey, 需要替换为自己的
  // const proxyUrl = '' // 如果公司需要通过代理才能访问外网,可以在此设置请求代理 
  
  // 1. 拼接规范请求串 CanonicalRequest
  var HTTPRequestMethod = 'POST'; // HTTP 请求方法(GET、POST )。此示例取值为 POST
  var CanonicalURI = '/'; // URI 参数,API 3.0 固定为正斜杠(/)
  var CanonicalQueryString = ""; // POST请求时为空
  var CanonicalHeaders = "content-type:application/json\nhost:ocr.tencentcloudapi.com\n";
  /**
   * 参与签名的头部信息,content-type 和 host 为必选头部,
   * 其中 host 指接口请求域名 POST 请求支持的 Content-Type 类型有:
   * 1. application/json(推荐),必须使用 TC3-HMAC-SHA256 签名方法。; 
   * 2. application/x-www-form-urlencoded,必须使用 HmacSHA1 或 HmacSHA256 签名方法。; 
   * 3. multipart/form-data(仅部分接口支持),必须使用 TC3-HMAC-SHA256 签名方法。
   */
  var SignedHeaders = "content-type;host";
  /**
   * 参与签名的头部信息的 key,可以说明此次请求都有哪些头部参与了签名,和 CanonicalHeaders 包含的头部内容是一一对应的。
   * content-type 和 host 为必选头部 。 
   * 注意: 
   * 1. 头部 key 统一转成小写; 
   * 2. 多个头部 key(小写)按照 ASCII 升序进行拼接,并且以分号(;)分隔 。 
   */
  // 传入需要做 HTTP 请求的正文 body
  var payload = {
      "ImageUrl":"https://imgcache.qq.com/open_proj/proj_qcloud_v2/gateway/product/ocr-demo/css/img/GeneralBasicOCR1.jpg", 
      "LanguageType":"auto" // 语言类型,可选,此处我用的是 auto 即自动
  } 
  var HashedRequestPayload = crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex'); // 哈希加密后的请求字符串 此示例结果是e4b76b87ed3234a73c7ff4665a4e9d566b7f9c959bc616a0b6aec403789a5924
  console.log(HashedRequestPayload)
  // 拼接
  var CanonicalRequest =  HTTPRequestMethod + '\n' +
    CanonicalURI + '\n' +
    CanonicalQueryString + '\n' +
    CanonicalHeaders + '\n' +
    SignedHeaders + '\n' +
    HashedRequestPayload;
  console.log('1. 拼接规范请求串' + CanonicalRequest);
  console.log('\n');

  // 2. 拼接待签名字符串
  var Algorithm = "TC3-HMAC-SHA256"; // 签名算法,目前固定为 TC3-HMAC-SHA256
  var RequestTimestamp = Math.round(new Date().getTime()/1000) + ""; // 请求时间戳,即请求头部的公共参数 X-TC-Timestamp 取值,取当前时间 UNIX 时间戳,精确到秒
  var t = new Date();
  var date = t.toISOString().substr(0, 10); // 计算 Date 日期   date = "2019-08-26"
  /**
   * Date 必须从时间戳 X-TC-Timestamp 计算得到,且时区为 UTC+0。
   * 如果加入系统本地时区信息,例如东八区,将导致白天和晚上调用成功,但是凌晨时调用必定失败。
   * 假设时间戳为 1551113065,在东八区的时间是 2019-02-26 00:44:25,但是计算得到的 Date 取 UTC+0 的日期应为 2019-02-25,而不是 2019-02-26。
   * Timestamp 必须是当前系统时间,且需确保系统时间和标准时间是同步的,如果相差超过五分钟则必定失败。
   * 如果长时间不和标准时间同步,可能导致运行一段时间后,请求必定失败,返回签名过期错误。
   */
  var CredentialScope = date + "/ocr/tc3_request"; 
  /**
   *  拼接 CredentialScope 凭证范围,格式为 Date/service/tc3_request , 
   * service 为服务名,慧眼用 faceid , OCR 文字识别用 ocr
   */

   // 将第一步拼接得到的 CanonicalRequest 再次进行哈希加密
  var HashedCanonicalRequest = crypto.createHash('sha256').update(CanonicalRequest).digest('hex'); 
  // 拼接
  var StringToSign = Algorithm + '\n' +
    RequestTimestamp + '\n' +
    CredentialScope + '\n' +
    HashedCanonicalRequest;
  console.log('2. 拼接待签名字符串' + StringToSign);
  console.log('\n');

  // 3. 计算签名
  var SecretDate = crypto.createHmac('sha256', "TC3"+SecretKey).update(date).digest();
  var SecretService = crypto.createHmac('sha256', SecretDate).update("ocr").digest();
  var SecretSigning = crypto.createHmac('sha256', SecretService).update("tc3_request").digest();
  var Signature = crypto.createHmac('sha256', SecretSigning).update(StringToSign).digest('hex');
  console.log('3. 计算签名' + Signature); 

  // 4. 拼接Authorization
  var Algorithm = "TC3-HMAC-SHA256";
  var Authorization =
    Algorithm + ' ' +
    'Credential=' + SecretId + '/' + CredentialScope + ', ' +
    'SignedHeaders=' + SignedHeaders + ', ' +
    'Signature=' + Signature
  console.log('4. 拼接Authorization' + Authorization)
  
  // 5.发送POST请求
  console.log(RequestTimestamp)
  // https模块 request options配置
  var options = {
      url: 'https://ocr.tencentcloudapi.com/',
      method:'POST',
      json: true,
      //proxy: proxyUrl,
      headers: {
        "Content-Type": "application/json",
        "Authorization": Authorization,
        "Host": "ocr.tencentcloudapi.com",
        "X-TC-Action": "GeneralBasicOCR",
        "X-TC-Version": "2018-11-19",
        "X-TC-Timestamp": RequestTimestamp,
        "X-TC-Region": "ap-guangzhou"
      },
      body: payload,
  };
  // 发起请求
  request(options, function (error, response, body) {
    if (error) throw new Error(error); 
    console.log(JSON.stringify(body))
  });

总结

本文以NodeJS语言为例,同步了一个可以直接执行的手动鉴权和请求发送代码demo,后续会逐步讲解其他语言(Python Java Go PHP .Net)的demo示例,欢迎大家持续关注~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导语
  • 案例背景
  • 原因分析
  • 解决方案
    • 前期准备
      • 具体代码
      • 总结
      相关产品与服务
      云 API
      云 API 是腾讯云开放生态的基石。通过云 API,只需少量的代码即可快速操作云产品;在熟练的情况下,使用云 API 完成一些频繁调用的功能可以极大提高效率;除此之外,通过 API 可以组合功能,实现更高级的功能,易于自动化, 易于远程调用, 兼容性强,对系统要求低。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档