HMAC Signature Parameter Description
1. Signature Parameter Description
HENGSHI SENSE supports multiple parameters when calculating the HMAC signature. The encryption field order for multiple parameter signatures is as follows:
appShareHash -> having -> where -> appParam -> utcSecond -> userAttr
Signature Text Format
app={appShareHash}&having=${having}&where=${where}&appParam=${appParam}&utcSecond=${utcSecond}&userAttr=${userAttr}
appParam Parameter
In the appParam parameter, only parameters with sig=true can be included in the HMAC signature calculation.
2. Calculate Signature Node.js Code Example
javascript
const having = null;
// Filter controls
const where = [
{
"datasetId": 3,
"fieldName": "Gender",
"use": "checkbox",
"kind": "function",
"op": "=",
"args": [
{ "kind": "field", "op": "Gender", "dataset": 2 },
{ "kind": "constant", "op": "Male" }
]
},
{
"appId": 100,
"datasetId": 2,
"kind": "formula",
"op": "{Gender}='Male'"
}
];
// Parameters
const appParam = [
{ "name": "Province Name", "value": "Hubei" },
// Only participate in signature calculation if sig = true
{ "name": "City Name", "value": "Wuhan", "sig": true },
{ "name": "Province Name", "value": "Hubei", "appId": 100 },
{ "name": "City Name", "value": "Wuhan", "appId": 100, "sig": true }
];
// Required only when HMAC expiration is enabled
const utcSecond = null; // new Date().getTime()
const hmacKey = 'HMAC signature key';
const appShareHash = 'app share hash';
// Text to participate in signature calculation, needs to be concatenated in parameter order
// 1. First, appShareHash must participate in the signature
let encryptText = `app=${appShareHash}`;
let queryString = '';
// 2. having participates in the signature only if it has a value
if (having && having.length > 0) {
const str = JSON.stringify(having);
encryptText += `&having=` + str;
// The value of the URL parameter needs to be encodeURIComponent
queryString += '&having=' + encodeURIComponent(str);
}
// 3. where participates in the signature only if it has a value
if (where && where.length > 0) {
const str = JSON.stringify(where);
encryptText += `&where=` + str;
// The value of the URL parameter needs to be encodeURIComponent
queryString += '&where=' + encodeURIComponent(str);
}
// 4. appParam
if (appParam && appParam.length > 0) {
// Filter out parameters with sig = true to participate in the signature
const encryptParams = appParam.filter(item => item.sig);
if (encryptParams.length > 0) {
encryptText += `&appParam=` + JSON.stringify(encryptParams);
}
// Note that the value of appParam in the URL parameter still includes all parameters (including those without sig=true)
// The value of the URL parameter needs to be encodeURIComponent
queryString += '&appParam=' + encodeURIComponent(JSON.stringify(appParam));
}
// 5. Required only when HMAC expiration is enabled
if (utcSecond) {
encryptText += '&utcSecond=' + utcSecond;
queryString += '&utcSecond=' + utcSecond;
}
// 6. When access is restricted to system users only and user attributes are used, sign the specified user attributes
if (userAttr) {
// Note: If user attributes are multi-valued or contain illegal characters, encodeURIComponent is required
encryptText += '&userAttr=' + userAttr;
queryString += '&userAttr=' + userAttr;
}
// Calculate HMAC signature
const signature = crypto.createHmac('sha1', hmacKey).update(encryptText).digest('hex');
queryString += '&signature=' + signature;
// Final signed link
const shareURL = `/share/app/${appShareHash}` + queryString.replace('&', '?', 1);