导语
该系列其他篇章:
V3手动鉴权失败之Go篇
V3手动鉴权失败之Python篇
V3手动鉴权失败之Java篇
V3手动鉴权失败之PHP篇
V3手动鉴权失败之C#篇
腾讯云 API 全新升级 3.0 ,该版本进行了性能优化且全地域部署、支持就近和按地域接入、访问时延下降显著,接口描述更加详细、错误码描述更加全面、SDK增加接口级注释,让您更加方便快捷的使用腾讯云产品。人脸识别、文字识别,语音识别等众多产品均已接入云API 3.0。
腾讯云API为了更好的让用户接入,已经封装好了多种语言的SDK,只需用户传入SecrectId、SectectKey以及接口入参,即可完成接口鉴权和请求发送,具体包括Python SDK、Java SDK、PHP SDK、Go SDK、NodeJS 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包:
npm i request
运行nodejs代码,可以完成v3鉴权,并发送http请求,收到具体的response响应。运行指令为:
node nodev3.js
具体的nodev3js代码如下,只需要简单复制,然后输入自己的SecretId和SecretKey两个字段即可:
// 本示例为V3接口鉴权之Node.js篇,以POST请求GeneralBasicOCR接口为例 // GET 请求的请求包大小不得超过 32KB。 // POST 请求使用签名方法为 HmacSHA1、HmacSHA256 时不得超过1MB 。 // POST 请求使用签名方法为 TC3-HMAC-SHA256 时支持 10MB。 这里使用 POST 示例 。
/**
- 详细文档需要参考 :
- 文字识别产品介绍文档: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 类型有:
- application/json(推荐),必须使用 TC3-HMAC-SHA256 签名方法。;
- application/x-www-form-urlencoded,必须使用 HmacSHA1 或 HmacSHA256 签名方法。;
- multipart/form-data(仅部分接口支持),必须使用 TC3-HMAC-SHA256 签名方法。
/
var SignedHeaders = "content-type;host";
/*- 参与签名的头部信息的 key,可以说明此次请求都有哪些头部参与了签名,和 CanonicalHeaders 包含的头部内容是一一对应的。
- content-type 和 host 为必选头部 。
- 注意:
- 头部 key 统一转成小写;
- 多个头部 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示例,欢迎大家持续关注~