接口鉴权

2024.05.28 10:03:25

    获取安全凭证

    易盾智能风控服务使用签名认证方法对接口进行鉴权,所有接口每一次请求都需要包含签名信息(signature 参数),以验证用户身份,防止身份被盗用和数据被恶意篡改。
    在第一次使用 API 之前,需获取安全凭证,安全凭证包括SecretId和SecretKey,SecretId是用于标识API调用者的身份,SecretKey是用于计算签名字符串的秘钥。SecretKey必须严格保管,避免泄露。获取路径为【易盾官网 - 智能风控 - 服务管理 - 点击查看产品密钥】。
    此方案配套V5、V6版本接口使用,老接口V4版本对应鉴权方法请参考接口鉴权V4

    生成签名参数 signature

    每次接口调用时,需要生成用于校验身份合法性的签名参数 signature,生成方法如下:

    1. 对所有请求参数(不包括 signature 参数),按照参数名ASCII码表升序顺序排序。如参数:foo=1, bar=2,foo_bar=3, baz=4 ,排序后的顺序是 bar=2, baz=4, foo=1, foo_bar=3;

    2. 将排序好的参数名和参数值对,拼装成字符串,格式为:key1value1key2value2…。根据上面示例,拼装结果为:bar2baz4foo1foo_bar3;

    3. 将安全凭证的secretKey,加到上一步拼装的参数字符串后面。根据上面示例,拼装结果为:bar2baz4foo1foo_bar3your_secretKey;

    4. 把 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)
    
    Online Chat Tel:95163223 Free trial