签名方法
为了防止API调用过程中被恶意篡改,调用任何一个API都需要携带签名
签名算法(MD5算法):
-
对所有API请求参数(包括公共参数和业务参数,但除去sign参数和值为空的参数),根据参数名称的ASCII码表的顺序排序。如:
a=1, c=3, b=2排序后的顺序是a=1, b=2,c=3。 -
将排序好的参数名和参数值按url拼装方式拼接在一起,根据上面的示例得到的结果为:
a=1&b=3&c=2。 -
在拼装的字符串后加上app的app_secret后,采用utf-8编码, 再进行MD5摘要,如 app_secret=xxxx:
md5(a=1&b=3&c=2&app_secret=xxxx) -
将摘要得到的字节流结果使用十六进制表示,并转换成小写。如:
hex(“helloworld”.getBytes(“utf-8”)).toLowerCase()= “68656c6c6f776f726c64”
签名示例
:::: tabs ::: tab JAVA
import org.apache.commons.lang3.StringUtils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SignUtils {
public static String md5Sign(Map<String, String> params, String appSecret) {
List<String> keys = Lists.newArrayList();
for (Map.Entry<String, String> entry : params.entrySet()) {
if ("sign".equals(entry.getKey())) {
continue;
}
if ("sign_type".equals(entry.getKey())) {
continue;
}
if (StringUtils.isNotBlank(entry.getValue())) {
keys.add(entry.getKey());
}
}
Collections.sort(keys);
List<String> temp = Lists.newArrayList();
for (String key : keys) {
String value = params.get(key);
temp.add(key + "=" + value);
}
temp.add("app_secret=" + appSecret);
String signStr = StringUtils.join(temp, "&");
return genMd5(signStr);
}
public static String genMd5(String info) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
log.error("genMd5 error:", e);
return null;
}
byte[] infoBytes = info.getBytes();
md5.update(infoBytes);
byte[] sign = md5.digest();
return byteArrayToHex(sign);
}
public static String byteArrayToHex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toLowerCase());
}
return sign.toString();
}
}
:::
::: tab Python
import hashlib
from copy import deepcopy
def md5_sign(org_params, app_secret):
params = deepcopy(org_parms)
if "sign" in params:
params.pop("sign")
if "sign_type" in params:
params.pop("sign_type")
lists = []
for item in params:
lists.append(item)
lists.sort()
tmp = []
for key in lists:
value = params[key]
if isinstance(value, bytes):
value = value.decode("utf-8")
if isinstance(key, bytes):
key = key.decode("utf-8")
tmp.append("=".join([key, str(value)]))
if isinstance(app_secret, bytes):
app_secret = app_secret.decode("utf-8")
tmp.append("=".join(['app_secret', app_secret]))
param_str = "&".join(tmp)
if not isinstance(param_str, bytes):
param_str = param_str.encode('utf-8')
return hashlib.md5(param_str).hexdigest()
def check_sign(param, app_secret):
data = deepcopy(param)
if "sign" in data:
org_sign = data.pop('sign')
else:
return False
if "sign_type" in data:
sign_type = data.pop('sign_type')
else:
return False
if not org_sign:
return False
if sign_type != 'MD5':
return False
nsg = md5_sign(data, app_secret)
print(nsg)
return org_sign == nsg
if __name__ == '__main__':
params = {"sing": "1", "method": "2", "id": "1231", "key": "apdfa", "sort": "serr"}
print(md5_sign(params, 'SECRET'))
::: ::::