腾讯云 API
会对每个请求进行身份验证,用户需要使用安全凭证,经过特定的步骤对请求进行签名 Signature
,每个请求都需要在公共请求参数中指定该签名结果并以指定的方式和格式发送请求 。
最近开始接触一些腾讯云 OCR
文字识别产品的工作,但总会遇到遇到各种鉴权签名的问题,而且完整的鉴权签名代码,官网上只有 Java
和 Python
版本的,于是我打算撸一份 Nodejs
版本的鉴权签名代码 。
本文适用于腾讯云 API 3.0
下的所有产品的鉴权签名 , 并将使用鉴权签名 v3
方法通过对腾讯云 OCR 文字识别服务的通用印刷体识别接口的完整调用分享一些鉴权签名的准备工作、开发思路及调用流程、调用结果及踩坑指南等 。
当然,您也可以直接使用我写好的代码,已经分享到了 Github,欢迎大家参阅及提出意见 。
在写鉴权签名之前,需要准备一些开发所需要的东西:腾讯云账号开发环境、开发工具 VSCode
、腾讯云账号注册、腾讯云账号实名认证、获取 API
密钥、 参考文档等 。
一: 下载安装
windows
环境下的 Nodejs
安装msi
文件,直接安装就可以,记住你的安装路径,后面做环境配置二: 配置环境变量
一般选择 msi
安装方式之后会自动帮配置好环境变量,也可以按如下步骤先查看下是否已配置好路径,若 Path
中有对应的路径,则无需再配置,若没有需要自行配置 ,可见下面四张图
win + r
打开 windows
运行面板sysdm.cpl
打开系统属性面板,见图三path
,添加一条你安装 Nodejs
的路径即可,我这里是 C:\Program Files\nodejs\;
,见图五、图六path
,添加一条你安装 npm
的路径即可,我这里是 C:\Users\User\AppData\Roaming\npm;
,见图七、图八三: 安装完成并配置好环境变量之后测试**
win + r
=> cmd
打开命令行面板,输入以下指令node -v
四: npm 安装
npm
即包管理工具,一般安装完 Nodejs
之后,npm
也会同时被安装 , 同样的 win + r
=> cmd
打开命令行面板,输入以下指令
npm --version
五: 正确安装
我们看下正确安装并测试安装之后,是什么样的,见下图,可以看到一般正确安装后,输入指令后会有版本号
一: 下载安装
二: 配置环境变量
Nodejs
和 npm
配置环境变量操作步骤一样,一般安装好 VSCode
, 也会同时被配置好环境的,但依然需要检查一下,没配置的则自行配置,已配置的则不用配置 。我这里是 E:\dep\Microsoft VS Code\bin
, 每条路径之后用 ;
隔开 。配置流程见以上图一 ~ 图四、图七、图八六张图 。SecretId
和 SecretKey
v3
、签名方法 v1
及 地域列表(腾讯云产品接口下的 Region
字段 ),这里强烈建议使用签名方法 v3
。OCR
文字识别产品之一,通用印刷体识别,支持多场景、任意版面下整图文字的识别。支持自动识别语言类型,同时支持自选语言种类(推荐),除中英文外,支持日语、韩语、西班牙语、法语、德语、葡萄牙语、越南语、马来语、俄语、意大利语、荷兰语、瑞典语、芬兰语、丹麦语、挪威语、匈牙利语、泰语等多种语言。应用场景包括:印刷文档识别、网络图片识别、广告图文字识别、街景店招识别、菜单识别、视频标题识别、头像文字识别等 。API
会对每个请求进行身份验证,用户需要使用安全凭证,经过特定的步骤对请求进行签名 Signature
,每个请求都需要在公共请求参数中指定该签名结果并以指定的方式和格式发送请求 。本节课的主要内容就是结合 通用印刷体识别 , 说明该如何开发接口鉴权 v3
签名代码及如何实现腾讯云产品调用 。 OCR
文字识别业务错误码 及 公共错误码 , 如果开发过程中遇到问题,到这里找一下,方便快速定位问题 。
TC3-HMAC-SHA256
签名方法相比以前的HmacSHA1
和HmacSHA256
签名方法,功能上覆盖了以前的签名方法,而且更安全,支持更大的请求,支持json
格式,性能有一定提升,建议使用该签名方法计算签名 。 云API
支持GET
和POST
请求。对于GET
方法,只支持Content-Type: application/x-www-form-urlencoded
协议格式。对于POST
方法,目前支持Content-Type: application/json
以及Content-Type: multipart/form-data
两种协议格式,json
格式绝大多数接口均支持,multipart
格式只有特定接口支持,此时该接口不能使用json
格式调用,参考具体业务接口文档说明 。推荐使用POST
请求,因为两者的结果并无差异,但GET
请求只支持32 KB
以内的请求包。 下面以云服务器查询广州区实例列表作为例子,分步骤介绍签名的计算过程。我们选择该接口是因为: 1. 云服务器默认已开通,该接口很常用; 2. 该接口是只读的,不会改变现有资源的状态 ; 3. 接口覆盖的参数种类较全,可以演示包含数据结构的数组如何使用 。
注意: 在示例中,不论公共参数或者接口的参数,我们尽量选择容易犯错的情况 。在实际调用接口时,请根据实际情况来,每个接口的参数并不相同,不要照抄这个例子的参数和值 。
这里以我的
SecretId
和SecretKey
为例写一个自己的签名,并会在写签名的过程中提到一些注意事项 。
const crypto = require('crypto') const request = require('request')
/** * 第一步: 拼接规范请求串 CanonicalRequest * 注意: 可对照代码看参数含义及注意事项 。 */ // 说明: HTTP 请求方法(GET、POST )。此示例取值为 POST var HTTPRequestMethod = 'POST'; // 说明: URI 参数,API 3.0 固定为正斜杠(/) var CanonicalURI = '/'; // 说明: POST请求时为空 var CanonicalQueryString = ""; /** 说明: * 参与签名的头部信息,content-type 和 host 为必选头部 , * content-type 必须为小写 , 推荐 content-type 值 application/json , 对应方法为 TC3-HMAC-SHA256 签名方法 。 * 其中 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 签名方法 。 * * 注意: * content-type 必须和实际发送的相符合 , 有些编程语言网络库即使未指定也会自动添加 charset 值 , * 如果签名时和发送时不 一致,服务器会返回签名校验失败。 */ var CanonicalHeaders = "content-type:application/json\nhost:ocr.tencentcloudapi.com\n"; /** 说明: * 参与签名的头部信息的 key,可以说明此次请求都有哪些头部参与了签名,和 CanonicalHeaders 包含的头部内容是一一对应的。 * content-type 和 host 为必选头部 。 * 注意: * 1. 头部 key 统一转成小写; * 2. 多个头部 key(小写)按照 ASCII 升序进行拼接,并且以分号(;)分隔 。 */ 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 即自动 } /** 说明: * 对请求体加密后的字符串 , 每个语言加密加密最终结果一致 , 但加密方法不同 , * 这里 nodejs 的加密方法为 crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex'); * 选择加密函数需要能够满足对 HTTP 请求正文做 SHA256 哈希 , 然后十六进制编码 , 最后编码串转换成小写字母的功能即可 。 */ var HashedRequestPayload = crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex'); // 最后拼接以上六个字段 , 注意中间用 '/n' 拼接 , 拼接格式一定要如下格式 , 否则会报错 var CanonicalRequest = HTTPRequestMethod + '\n' + CanonicalURI + '\n' + CanonicalQueryString + '\n' + CanonicalHeaders + '\n' + SignedHeaders + '\n' + HashedRequestPayload; console.log('1. 拼接规范请求串' + '\n' + CanonicalRequest);
// 2. 拼接待签名字符串 // 签名算法,接口鉴权v3为固定值 TC3-HMAC-SHA256 var Algorithm = "TC3-HMAC-SHA256"; // 请求时间戳,即请求头部的公共参数 X-TC-Timestamp 取值,取当前时间 UNIX 时间戳,精确到秒 var RequestTimestamp = Math.round(new Date().getTime()/1000) + ""; /** * Date 必须从时间戳 X-TC-Timestamp 计算得到,且时区为 UTC+0。 * 如果加入系统本地时区信息,例如东八区,将导致白天和晚上调用成功,但是凌晨时调用必定失败。 * 假设时间戳为 1551113065,在东八区的时间是 2019-02-26 00:44:25,但是计算得到的 Date 取 UTC+0 的日期应为 2019-02-25,而不是 2019-02-26。 * Timestamp 必须是当前系统时间,且需确保系统时间和标准时间是同步的,如果相差超过五分钟则必定失败。 * 如果长时间不和标准时间同步,可能导致运行一段时间后,请求必定失败,返回签名过期错误。 */ var t = new Date(); var date = t.toISOString().substr(0, 10); // 计算 Date 日期 date = "2019-08-26" /** * 拼接 CredentialScope 凭证范围,格式为 Date/service/tc3_request , * service 为服务名,慧眼用 faceid , OCR 文字识别用 ocr */ var CredentialScope = date + "/ocr/tc3_request"; // 将第一步拼接得到的 CanonicalRequest 再次进行哈希加密 var HashedCanonicalRequest = crypto.createHash('sha256').update(CanonicalRequest).digest('hex'); // 拼接 StringToSign var StringToSign = Algorithm + '\n' + RequestTimestamp + '\n' + CredentialScope + '\n' + HashedCanonicalRequest; console.log('2. 拼接待签名字符串' + '\n' + StringToSign);
// 3. 计算签名 Signature var SecretKey = "请替换为自己的 SecretKey"; 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 SecretId = "请替换为自己的 SecretId"; // SecretId, 需要替换为自己的 var Algorithm = "TC3-HMAC-SHA256"; var Authorization = Algorithm + ' ' + 'Credential=' + SecretId + '/' + CredentialScope + ', ' + 'SignedHeaders=' + SignedHeaders + ', ' + 'Signature=' + Signature console.log('4. 拼接Authorization' + '\n' + Authorization)
// 5. 发送POST请求 options 配置 var options = { url: 'https://ocr.tencentcloudapi.com/', method:'POST', json: true, 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)) });
帮助我们更少的犯错
原创声明,本文系作者授权云+社区发表,未经许可,不得转载。
如有侵权,请联系 yunjia_community@tencent.com 删除。
我来说两句