OneNET MQ authentication mechanism mainly ensures access security by:
Token consists of multiple parameters, as shown below:
Name | Type | Required | Parameter description | Example |
---|---|---|---|---|
version | string | Yes | The version number of the parameter group, which currently supports only a date format like “2018-10-31”. | 2018-10-31 |
res | string | Yes | Fixed as mqs/{instance name} | mqs/test_mq |
et | int | Yes | Access expiration time expirationTime, unix time. When the et time in an access parameter is earlier than the current time, the access parameter is considered expired and the access is refused. | 1537255523 represents: Beijing Time 2018-09-18 15:25:23 |
method | string | Yes | signatureMethod supports md5、sha1、sha256 | sha256 |
sign | string | Yes | Signature result string Signature |
Special instructions about token parameters:
An algorithm for generating parameter sign is as follows:
sign = base64(hmac_<method>(base64decode(accessKey), utf-8(StringForSignature)))
Where:
StringForSignature is constituted as follows:
StringForSignature = et + '\n' + method + '\n' + res+ '\n' + version
Note: Each parameter is incorporated in a key=value format, but only value participates in computing the components of the signature string StringForSignature. If token parameter is as follows:
et = 1537255523
method = sha1
res = mqs/test_mq
version = 2018-10-31
Then the string used to calculate a signature, StringForSignature, is (in the order of et, method, res and version).
StringForSignature = "1537255523" + "\n" + "sha1"+ "\n" + "mqs/test_mq"+ "\n" + "2018-10-31"
After sign is computed, each parameter is expressed in the form of key=value, using '&' as a separator, as illustrated below:
version=2018-10-31&res=mqs/test_mq&et=1537255523&method=sha1&sign=ZjA1NzZlMmMxYzIOTg3MjBzNjYTI2MjA4Yw=
Token value in the form of key=value requires URL encoding, and the special symbols to be encoded are as follows:
No. | Symbol | Encode |
---|---|---|
1 | + | %2B |
2 | 空格 | %20 |
3 | / | %2F |
4 | ? | %3F |
5 | % | %25 |
6 | # | %23 |
7 | & | %26 |
8 | = | %3D |
After coding, the actually transmitted token in the above example is:
version=2018-10-31&res=mqs%2Ftest_mq&et=1537255523&method=sha1&sign=ZjA1NzZlMmMxYzIOTg3MjBzNjYTI2MjA4Yw%3D
python code example
import base64
import hmac
import time
from urllib.parse import quote
def token(name,access_key):
version = '2018-10-31'
res = 'mqs/%s' % name # access MQ via MQ instance name
# user-defined token expiration time
et = str(int(time.time()) + 3600)
# signature method, supports md5, sha1 and sha256
method = 'sha1'
# decode access_key
key = base64.b64decode(access_key)
# calculate sign
org = et + '\n' + method + '\n' + res + '\n' + version
sign_b = hmac.new(key=key, msg=org.encode(), digestmod=method)
sign = base64.b64encode(sign_b.digest()).decode()
# the value part is URL encoded, and the method/res/version value is
sign = quote(sign, safe='')
res = quote(res, safe='')
# token parameters are concatenated
token = 'version=%s&res=%s&et=%s&method=%s&sign=%s' % (version, res, et, method, sign)
return token
if __name__ == '__main__':
name = 'test_mq'
access_key = 'KuF3NT/jUBJ62LNBB/A8XZA9CqS3Cu79B/ABmfA1UCw='
print(token(name,access_key))
Java code example
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Token {
public static String assembleToken(String version, String resourceName, String expirationTime, String signatureMethod, String accessKey)
throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
StringBuilder sb = new StringBuilder();
String res = URLEncoder.encode(resourceName, "UTF-8");
String sig = URLEncoder.encode(generatorSignature(version, resourceName, expirationTime
, accessKey, signatureMethod), "UTF-8");
sb.append("version=")
.append(version)
.append("&res=")
.append(res)
.append("&et=")
.append(expirationTime)
.append("&method=")
.append(signatureMethod)
.append("&sign=")
.append(sig);
return sb.toString();
}
public static String generatorSignature(String version, String resourceName, String expirationTime, String accessKey, String signatureMethod)
throws NoSuchAlgorithmException, InvalidKeyException {
String encryptText = expirationTime + "\n" + signatureMethod + "\n" + resourceName + "\n" + version;
String signature;
byte[] bytes = HmacEncrypt(encryptText, accessKey, signatureMethod);
signature = Base64.getEncoder().encodeToString(bytes);
return signature;
}
public static byte[] HmacEncrypt(String data, String key, String signatureMethod)
throws NoSuchAlgorithmException, InvalidKeyException {
//construct a secret key from the given byte array, and the second parameter specifies a key algorithm
SecretKeySpec signinKey = null;
signinKey = new SecretKeySpec(Base64.getDecoder().decode(key),
"Hmac" + signatureMethod.toUpperCase());
//generate a Mac object for the specified Mac algorithm
Mac mac = null;
mac = Mac.getInstance("Hmac" + signatureMethod.toUpperCase());
//initialize the Mac object with the given ke
mac.init(signinKey);
//Mac operation is finished
return mac.doFinal(data.getBytes());
}
public enum SignatureMethod {
SHA1, MD5, SHA256;
}
public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
String version = "2018-10-31";
String resourceName = "mqs/test_mq";
String expirationTime = System.currentTimeMillis() / 1000 + 100 * 24 * 60 * 60 + "";
String signatureMethod = SignatureMethod.SHA1.name().toLowerCase();
String accessKey = "KuF3NT/jUBJ62LNBB/A8XZA9CqS3Cu79B/ABmfA1UCw=";
String token = assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);
System.out.println("Authorization:" + token);
}
}