接口鉴权
2024.11.25 17:57:07
获取安全凭证
易盾智能风控服务使用签名认证方法对接口进行鉴权,所有接口每一次请求都需要包含签名信息(signature 参数),以验证用户身份,防止身份被盗用和数据被恶意篡改。
在第一次使用 API 之前,需获取安全凭证,安全凭证包括SecretId和SecretKey,SecretId是用于标识API调用者的身份,SecretKey是用于计算签名字符串的秘钥。SecretKey必须严格保管,避免泄露。获取路径为【易盾官网 - 智能风控 - 服务管理 - 点击查看产品密钥】。
此方案配套V5、V6版本接口使用,老接口V4版本对应鉴权方法请参考接口鉴权V4。
生成签名参数 signature
每次接口调用时,需要生成用于校验身份合法性的签名参数 signature,生成方法如下:
-
对所有请求参数(不包括 signature 参数),按照参数名ASCII码表升序顺序排序。如参数:foo=1, bar=2,foo_bar=3, baz=4 ,排序后的顺序是 bar=2, baz=4, foo=1, foo_bar=3;
-
将排序好的参数名和参数值对,拼装成字符串,格式为:key1value1key2value2…。根据上面示例,拼装结果为:bar2baz4foo1foo_bar3;
-
将安全凭证的secretKey,加到上一步拼装的参数字符串后面。根据上面示例,拼装结果为:bar2baz4foo1foo_bar3your_secretKey;
-
把 3 中的字符串,采用 UTF-8 编码,使用 MD5算法(128位长度)对字符串进行摘要计算,得到signature参数值(32位十六进制小写字符串)。
示例代码
//详细签名方法见:https://github.com/yidun/irisk-openapi-demo/blob/main/irisk-openapi-java-demo/src/main/java/com/netease/irisk/openapi/demo/util/SignatureUtils.java
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.Map;
@Slf4j
public class SignatureUtil {
/**
* 签名方法,注意params的value不要为null(空字符串和null的区别),否则可能造成前后端签名不一致
*
* @param secretKey
* @param params
* @return
*/
public static String getSignature(String secretKey, Map<String, String> params) {
String signature = "";
if (StringUtils.isEmpty(secretKey) || ObjectUtils.isEmpty(params)) {
return signature;
}
try {
// 1. 参数名按照ASCII码表升序排序
String[] keys = params.keySet().toArray(new String[0]);
Arrays.sort(keys);
// 2. 按照排序拼接参数名与参数值
StringBuilder paramBuffer = new StringBuilder();
for (String key : keys) {
paramBuffer.append(key).append(params.get(key) == null ? "" : params.get(key));
}
// 3. 将secretKey拼接到最后
paramBuffer.append(secretKey);
// 4. MD5是128位长度的摘要算法,用16进制表示,一个十六进制的字符能表示4个位,所以签名后的字符串长度固定为32个十六进制字符。
signature = DigestUtils.md5Hex(paramBuffer.toString().getBytes("UTF-8"));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return signature;
}
/**
* 拼接组装参与计算的params参数示例
* 不同接口校验参数不同,详见目录下的demo文件: https://github.com/yidun/irisk-openapi-demo/tree/main/irisk-openapi-java-demo/src/main/java/com/netease/irisk/openapi/demo/mobile
*/
public Map<String,String> getParamsMap(){
Map<String, String> signMap = new HashMap<>(32);
signMap.put("version", version);
signMap.put("secretId", secretId);
signMap.put("businessId", businessId);
signMap.put("timestamp", timestamp);
signMap.put("nonce", nonce);
signMap.put("xxx", xxx);
signMap.put("xxx", xxx);
return signMap;
}
}
# 签名方法样例
def __init__(self, secret_id, secret_key, business_id, version):
"""
Args:
secret_id (str) 产品id,每个应用接入时,会分配secretId和私钥secretKey。
secret_key (str) 产品密钥,每个应用接入时,会分配secretId和私钥secretKey。
business_id (str) 每个业务接入时,均会分配业务 ID
version (str) 版本号,如400
"""
self.secret_id = secret_id
self.secret_key = secret_key
self.business_id = business_id
self.version = version
def gen_signature(self, params):
buff = ""
for k in sorted(params.keys()):
buff += str(k) + str(params[k])
buff += self.secret_key
return hashlib.md5(buff.encode("utf8")).hexdigest()
# 拼接组装参与计算的params参数示例
# 不同接口校验参数不同,详见目录下的demo文件: https://github.com/yidun/irisk-openapi-demo/tree/main/irisk-openapi-python-demo/mobile
def get_signature_params(self, params):
signature_params = {
"secretId": params["secretId"],
"businessId": params["businessId"],
"nonce": params["nonce"],
"timestamp": params["timestamp"],
"version": params["version"],
"xxx": params["..."],
"xxx": params["..."],
}
return signature_params
详细签名方法见:https://github.com/yidun/irisk-openapi-demo/blob/main/irisk-openapi-php-demo/util.php
/**
* 生成签名方法
* 不同openapi的签名参数不同
* @param $secretKey
* @param $params
* @return string
*/
function gen_signature($secretKey, $params){
ksort($params);
$buff="";
foreach($params as $key=>$value){
if($value !== null) {
$buff .=$key;
$buff .=$value;
}
}
$buff .= $secretKey;
return md5($buff);
}
/**
* 拼接组装参与计算的params参数示例
* 不同接口校验参数不同,详见目录下的demo文件: https://github.com/yidun/irisk-openapi-demo/tree/main/irisk-openapi-php-demo/mobile
*/
def get_signature_params(self, params):
signature_params = {
"secretId": params["secretId"],
"businessId": params["businessId"],
"nonce": params["nonce"],
"timestamp": params["timestamp"],
"version": params["version"],
"xxx": params["..."],
"xxx": params["..."],
}
return signature_params
详细签名方法见:https://github.com/yidun/irisk-openapi-demo/blob/main/irisk-openapi-csharp-demo/Utils.cs
// 根据secretKey和parameters生成签名
public static String genSignature(String secretKey, Dictionary<String, String> parameters)
{
parameters = parameters.OrderBy(o => o.Key, StringComparer.Ordinal).ToDictionary(o => o.Key, p => p.Value);
StringBuilder builder = new StringBuilder();
foreach (KeyValuePair<String, String> kv in parameters)
{
builder.Append(kv.Key).Append(kv.Value);
}
builder.Append(secretKey);
String tmp = builder.ToString();
MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(Encoding.UTF8.GetBytes(tmp));
builder.Clear();
foreach (byte b in result)
{
builder.Append(b.ToString("x2").ToLower());
}
return builder.ToString();
}
/**
*
* 拼接组装参与计算的params参数示例
* 不同接口校验参数不同,详见目录下的demo文件: https://github.com/yidun/irisk-openapi-demo/blob/main/irisk-openapi-csharp-demo
*/
public Dictionary<String, String> getParamsMap(){
Dictionary<String, String> parameters = new Dictionary<String, String>();
parameters.Add("version", version);
parameters.Add("secretId", secretId);
parameters.Add("businessId", businessId);
parameters.Add("timestamp", timestamp);
parameters.Add("nonce", nonce);
parameters.Add("xxx", ...);
parameters.Add("xxx", ...);
return parameters;
}
详细签名方法见:https://github.com/yidun/irisk-openapi-demo/blob/main/irisk-openapi-nodejs-demo/mobile/utils.js
//生成签名算法--工具方法
var genSignature = function (secretKey, paramsJson) {
var sorter = function (paramsJson) {
var sortedJson = {};
var sortedKeys = Object.keys(paramsJson).sort();
for (var i = 0; i < sortedKeys.length; i++) {
sortedJson[sortedKeys[i]] = paramsJson[sortedKeys[i]]
}
return sortedJson;
}
var sortedParam = sorter(paramsJson);
var needSignatureStr = "";
for (var key in sortedParam) {
var value = sortedParam[key];
needSignatureStr = needSignatureStr + key + value;
}
needSignatureStr += secretKey;
signatureMethod = "md5";
return crypto.createHash(signatureMethod).update(needSignatureStr, "utf-8").digest("hex");
};
不同接口校验参数不同,详见目录下的demo文件:https://github.com/yidun/irisk-openapi-demo/tree/main/irisk-openapi-nodejs-demo/mobile
// 拼接组装参与计算的params参数示例
var post_data = {
secretId: secretId,
businessId: businessId,
version: version,
timestamp: timestamp,
nonce: nonce,
xxx: ...,
xxx: ...,
}
// 生成签名信息
func genSignature(params map[string]interface{}) string {
var signatureParams map[string]string
signatureParams = make(map[string]string)
signatureParams["secretId"] = params["secretId"].(string)
signatureParams["businessId"] = params["businessId"].(string)
signatureParams["nonce"] = params["nonce"].(string)
signatureParams["version"] = params["version"].(string)
signatureParams["timestamp"] = params["timestamp"].(string)
signatureParams["ip"] = params["ip"].(string)
signatureParams["token"] = params["token"].(string)
var paramStr string
keys := make([]string, 0, len(signatureParams))
for k := range signatureParams {
keys = append(keys, k)
}
sort.Strings(keys)
for _, key := range keys {
paramStr += key + signatureParams[key]
}
paramStr += secretKey
md5Reader := md5.New()
md5Reader.Write([]byte(paramStr))
return hex.EncodeToString(md5Reader.Sum(nil))
}
// 不同接口校验参数不同,详见目录下的demo文件:https://github.com/yidun/irisk-openapi-demo/tree/main/irisk-openapi-go-demo/mobile
// 拼接组装参与计算的params参数示例
var signatureParams map[string]string
signatureParams = make(map[string]string)
signatureParams["secretId"] = params["secretId"].(string)
signatureParams["businessId"] = params["businessId"].(string)
signatureParams["nonce"] = params["nonce"].(string)
signatureParams["version"] = params["version"].(string)
signatureParams["timestamp"] = params["timestamp"].(string)
signatureParams["xxx"] = params["..."].(string)
signatureParams["xxx"] = params["..."].(string)