騰訊云 OCR-通用印刷體識別接口中其中一步是關(guān)于鑒權(quán)簽名
文檔示例中以后端(PHP NodeJS 等為例)卻沒有前端部分的調(diào)用方式(估計是非常規(guī)方式進行調(diào)用)代咸,基于技術(shù)研究原因與好奇心下還是覺得既然是 http 接口侄泽,前端應(yīng)該也能調(diào)用祭饭,并開始 coding...
前端利用 jquery(1.11.3)發(fā)送請求吕座,過程中卡在加密這個步驟中盈匾,加密使用的是 crypto-js
先按接口文檔拼接簽名字符串通過 crypto-js
的 HMAC-SHA1
進行加密忿薇,但發(fā)現(xiàn)加密這步驟并非如此簡單。
無論怎樣生成簽名串岳链,前端調(diào)用返回的都是 bad request,并且提示信息不清晰劲件,不知哪個環(huán)節(jié)出問題掸哑,后來只能利用啟動 wamp 借助官方文檔中 php 生成簽名的例子 + postman 作嘗試,終于成功零远,發(fā)現(xiàn)忽略了一個重點(我漏了“將 orignal 附加到簽名結(jié)果的末尾”這個步驟):
使用 HMAC-SHA1 算法對請求進行加密(SHA1算法加密后的輸出必須是原始的二進制數(shù)據(jù)苗分,否則簽名失敗)牵辣;
對 orignal 使用 HMAC-SHA1 算法進行簽名摔癣,然后將 orignal 附加到簽名結(jié)果的末尾,再進行 Base64 編碼纬向,得到最終的 sign择浊;
php 中是這樣反映出來(.$srcStr)
$signStr = base64_encode(hash_hmac('SHA1', $srcStr, $secret_key, true).$srcStr);
前端 crypto-js
庫加密的問題就出在這里,php 中 hash_hmac('SHA1', $srcStr, $secret_key, true)
是生成二進制數(shù)據(jù)逾条,但居然能拼接 $srcStr
源簽名串
但前端 crypto-js
這樣拼接字符串是會出錯的
originalStr = `a=${appid}&b=&k=${secretId}&e=${expired}&t=${time}&r=${random}&u=0&f=`;
sign = CryptoJS.HmacSHA1(originalStr, secretKey) + originalStr; // 拼接字符串
authorization = CryptoJS.enc.Base64.stringify(sign); // TypeError: t.clamp is not a function
然后查看 Node JS 簽名示例
bin = Buffer.concat([res,data]);
看到 Buffer concat 方法琢岩,想 HmacSHA1 出來的是一個 wordArray 類型(二進制數(shù)據(jù)?)师脂,crypto Base64 拼接字符串會出錯担孔,但是否會有像 Buffer 這樣的 concat 方法,果然最終居然在 wordArray 中找到 concat 方法吃警,多番嘗試下中與成功糕篇!
originalStr = `a=${appid}&b=&k=${secretId}&e=${expired}&t=${time}&r=${random}&u=0&f=`,
originalStrWordArray = CryptoJS.enc.Utf8.parse(originalStr), // 將源簽名串解析成 wordArray 類型
signWordArray = CryptoJS.HmacSHA1(originalStr, secretKey),
concatWordArray = signWordArray.concat(originalStrWordArray), // 通過 wordArray concat 將兩個數(shù)據(jù)進行拼接合并
authorization = CryptoJS.enc.Base64.stringify(concatWordArray); // 最終進行 Base64 編碼,成功生成簽名串
這次分享有經(jīng)驗的大神可能很快就知道如何處理酌心,但于我而言拌消,就拼接這里確實卡了很長一段時間,查 crypto-js 用法沒提到 concat 谒府,就在想放棄前端生成簽名串的時候拼坎,再看 nodejs 居然發(fā)現(xiàn)了這個方法浮毯,在前端調(diào)用接口成功的那一刻,那種成功感真的滿滿泰鸡,因此就在這里分享债蓝,并當(dāng)留念,鼓舞自己繼續(xù)前進盛龄。