一直在用腾讯的人脸比对功能,由于最近腾讯人脸比对功能升级,原有鉴权方式不再可用,新版的鉴权方式却没有c++的SDK,提交工单后,官方反馈是自己参照java写一个接口鉴权。
当时真是尴尬至极,工作计划全部打乱,原计划半天工作量,又要后延,只能加班搞了,还好我们在QT平台上搞,也不用集成太多的三方库,下面把本人的鉴权接口提供给大家,以供参考。
------------------------------------------------头文件---------------------------------------------------------------------
struct stNetRqstPara
{
QString strKey; //!键值
QString strValue; //!vlue
stNetRqstPara(QString i_strKey, QString i_strValue)
{
strKey = i_strKey;
strValue = i_strValue;
}
};
struct ST_TencentV1SignData
{
//!请求类型(true POSt,false GET)
bool bPostFlag;
QString strHost;
ST_TencentV1SignData()
{
bPostFlag = true;
}
};
class CTencentV1Sign : public CTecncentSign
{
public:
CTencentV1Sign(const QList
~CTencentV1Sign(void);
public:
//设置加密信息
void SetSingInfo(const ST_TencentV1SignData& stSignData);
//开始加密
void EnSignInfo();
//!获取加密结果
QList
private:
//!获得请求后的字符串
QString GetRequstString();
//!获得原文字符串
QString GetSrcString(const QString& strRequstStr);
//!加密字符串
QString SignatureStr(const QString& strSrcStr);
private:
//!网络请求列表
QList
//!加密数据
ST_TencentV1SignData m_stSignData;
};
-------------------------------------------源文件----------------------------------------------
/*!
* \class CTencentV1Sign
*
* \brief 腾讯加密密钥V1生成类
*
* \date: 2018/11/19 10:40
* \note: 说明
*/
#include "TencentV1Sign.h"
#include "QDateTime"
#include "TencentInerDef.h"
#include "QMap"
#define TECENT_REQUST_PATH ("/")
CTencentV1Sign::CTencentV1Sign(const QList
{
m_listPara = listPara;
}
CTencentV1Sign::~CTencentV1Sign(void)
{
}
/*!
* \brief 设置加密信息
*
* \param_in stSignData 加密结构体 参见定义
* \retval void
*
* \note: 注意事项(可选)
*/
void CTencentV1Sign::SetSingInfo(const ST_TencentV1SignData& stSignData)
{
m_stSignData = stSignData;
}
/*!
* \brief 加密信息---主函数
*
* \param_in void
* \retval void
*
* \note: 注意事项(可选)
*/
void CTencentV1Sign::EnSignInfo()
{
//!增加时间戳
qint64 illDatespec = QDateTime::currentMSecsSinceEpoch();
QString strUnixSpec = QString("%1").arg(illDatespec/1000);
m_listPara.append(stNetRqstPara(STR_V1_TIME_HEADER, strUnixSpec));
//!增加随机整数
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
int iNone = qrand() % 100000;
m_listPara.append(stNetRqstPara(STR_V1_NONE_HEADER, QString("%1").arg(iNone)));
//!获得请求字符串
QString strRequstStr = GetRequstString();
//!拼接原文字符串
QString strSrcStr = GetSrcString(strRequstStr);
//!加密文本
QString strSignature = SignatureStr(strSrcStr);
m_listPara.append(stNetRqstPara(STR_V1_SIGN_PARAKEY, strSignature));
}
/*!
* \brief 加密请求字符串
*
* \param_in void
* \retval QString
*
* \note: 注意事项(可选)
*/
QString CTencentV1Sign::GetRequstString()
{
//!排序
QMap
foreach(stNetRqstPara stparaData, m_listPara)
{
paraMap.insert(stparaData.strKey, stparaData.strValue);
}
//!拼接字符串
QString strRequstValue;
QMap
for (; paraItr != paraMap.end(); paraItr++)
{
strRequstValue += QString("%1=%2&").arg(paraItr.key(), paraItr.value());
}
if(!strRequstValue.isEmpty())
{
strRequstValue = strRequstValue.left(strRequstValue.length()-1);
}
return strRequstValue;
}
/*!
* \brief 拼装原文字符串
*
* \param_in strRequstStr 请求加密字符串
* \retval QString
*
* \note: 注意事项(可选)
*/
QString CTencentV1Sign::GetSrcString(const QString& strRequstStr)
{
QString strSrcStr;
QString strMethod = "POST";
if (!m_stSignData.bPostFlag)
{
strMethod = "GET";
}
strSrcStr += strMethod;
strSrcStr += m_stSignData.strHost;
strSrcStr += TECENT_REQUST_PATH;
strSrcStr += "?";
strSrcStr += strRequstStr;
return strSrcStr;
}
/*!
* \brief 加密原文字符串
*
* \param_in strSrcStr 请求原文字符串
* \retval QString
*
* \note: 注意事项(可选)
*/
QString CTencentV1Sign::SignatureStr(const QString& strSrcStr)
{
QByteArray qByteSigna = HMACSHA256Encode(strSrcStr.toUtf8(), m_cstrScretKey.toUtf8());
return qByteSigna.toBase64();
}
其中HMACSHA256Encode实现如下所示
QByteArray HMACSHA256Encode(QByteArray strMsg, QByteArray strKey)
{
QMessageAuthenticationCode sqqs(QCryptographicHash::Sha256);
sqqs.setKey(strKey);
sqqs.addData(strMsg);
QByteArray bb = sqqs.result();
return bb;
}
使用方法非常简单
//!初始化请求信息--post?host
ST_TencentV1SignData stSignData;
stSignData.bPostFlag = true;
stSignData.strHost = STR_TECNENT_IAI_HOST;
//将请求参数信息赋给加密对象
CTencentV1Sign signObj(m_PostParaList);
signObj.SetSingInfo(stSignData);
//!开始加密
signObj.EnSignInfo();
m_PostParaList = signObj.GetSignature();
获得加密参数后,既可以通过官方的方式进行拼接参数了,因为系统原有网络请求处理模式,所以接口鉴权类只是生产了所需的参数信息,剩下的简单拼装一下就ok了。
https://cvm.tencentcloudapi.com/?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE&Signature=EliP9YW3pW28FpsEdkXt%2F%2BWcGeI%3D&Timestamp=1465185768&Version=2017-03-12