1. Signature Parameter Explanation
HENGSHI 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}
In the appParam parameter, only parameters with sig=true can participate in the calculation of the hmac signature.
2. Example Node.js Code for Calculating Signatures
javascript
const having = null;
// Filter control
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 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. appShareHash must participate in the signature
let encryptText = `app=${appShareHash}`
let queryString = ''
// 2. having participates in the signature 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 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 that participate in the signature only if sig = true
const encryptParams = appParam.filter(item => appParam.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(appParam)
}
// 5. Required only when HMAC expiration is enabled
if(utcSecond){
encryptText += '&utcSecond=' + utcSecond
queryString += '&utcSecond=' + utcSecond
}
// 6. When only allowing access by users within the system and using user attributes, sign the specified user attributes
if(userAttr){
// Note: If the user attribute is multi-valued or contains illegal characters, it needs to be encodeURIComponent
encryptText += '&userAttr=' + userAttr
queryString += '&userAttr=' + userAttr
}
// Calculate HMAC signature
const signature = crypto.createHmac('sha1', hmacKey).update(encryptText).digest('hex');
queryString += '&signature=' + signature
// Final URL with signature
const shareURL = `/share/app/${appShareHash}` + queryString.replace('&', '?', 1)