跳转至

签名机制

签名说明

  • 公共参数(sign除外) + 私有参数+ appsecret 一起按照字典升序排列后以“&”相接
  • 切记 appsecret 只参与签名,不参与传递
  • 公共参数和私有参数里非必传字段不是必须参与签名和传递的,
    任何参数如果参与了签名,就一定要参与传递,否则签名不通过
  • 令牌创建-接口是没有公用参数,只需私有参数参与签名,见如下令牌创建签名示例
  • 公共参数 的传递都是放在queryString或表单之中,不能放在别的位置
  • 私有参数根据Content-Type分为两类: application/x-www-form-urlencodedapplication/json,具体使用哪种查看每个接口里的 请求示例 部分
  • 绝大部分接口均是表单传参形式application/x-www-form-urlencoded
    签名方式参考form传参业务签名示例
  • 少量接口是需要传递大量数据的业务情况下,传参形式为application/json
    签名方式参考json传参业务签名示例

令牌创建签名示例

  • 假设私有参数如下:

    timestamp:1469691921
    grant_type:client_credential
    appid:30000003
    

  • 假设appsecret如下

    appsecret:f4cc82386a1cdddcc98e4f53b1115a62
    

  • 对上述所有参数进行字典升序排列。排好序的参数信息依次为

    appid:30000003
    appsecretf4cc82386a1cdddcc98e4f53b1115a62
    grant_type:client_credential
    timestamp:1469691921
    

  • 以&拼接排好序的参数,参数的形式为key=value,拼接结果如下

    appid=30000003&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&timestamp=1469691921
    

  • 生成签名

    sign=sha256(appid=30000003&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&timestamp=1469691921)
    计算结果为:45dc064aa755ac2146aa24cf7baea3cf3668970538fba7b70ccef39a3ad055b1
    开发者可以用这个示例检查自己的sha256算法是否有效
    

  • java签名代码如下:

    import org.apache.commons.codec.digest.DigestUtils;
    
    import java.util.Iterator;
    import java.util.Map.Entry;
    import java.util.TreeMap;
    
    public class Signs {
        public static void main(String[] args) {
            int appId = 30000003;
            String appSecret = "f4cc82386a1cdddcc98e4f53b1115a62";
            int timeStamp = 1469691921;
            String grantType = "client_credential";
    
            TreeMap<String, Object> params = new TreeMap();
            params.put("appid", appId);
            params.put("grant_type", grantType);
            params.put("timestamp", timeStamp);
            params.put("appsecret", appSecret);
            StringBuilder stringBuilder = new StringBuilder();
            Iterator tmp = params.entrySet().iterator();
    
            while (tmp.hasNext()) {
                Entry<String, Object> entry = (Entry) tmp.next();
                stringBuilder.append(((String) entry.getKey()).trim());
                stringBuilder.append("=");
                stringBuilder.append(entry.getValue().toString().trim());
                stringBuilder.append("&");
            }
    
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
    
            String signContent = stringBuilder.toString();
            System.out.println("打印签名字符串:" + signContent);
    
            String sign = DigestUtils.sha256Hex(signContent);
            System.out.println("签名结果sign:" + sign);
    
        }
    }
    
    
    运行结果:
    打印签名字符串:appid=30000003&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&timestamp=1469691921
    签名结果sign:45dc064aa755ac2146aa24cf7baea3cf3668970538fba7b70ccef39a3ad055b1
    

form传参业务签名示例

  • 假设公共参数如下:
    access_token:1ba50b8f418a3ceeba989d7b789de149
    timestamp:1469691921
    grant_type:client_credential
    
  • 假设私有参数如下:

    name:alask
    remark:传参示例
    

  • 假设appsecret如下

    appsecret:f4cc82386a1cdddcc98e4f53b1115a62
    

  • 对上述所有参数进行字典升序排列。排好序的参数信息依次为

    access_token:1ba50b8f418a3ceeba989d7b789de149
    appsecret:f4cc82386a1cdddcc98e4f53b1115a62
    grant_type:client_credential
    name:alask
    remark:传参示例
    timestamp:1469691921
    

  • 以&拼接排好序的参数,参数的形式为key=value,拼接结果如下

    access_token=1ba50b8f418a3ceeba989d7b789de149&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&name=alask&remark=传参示例&timestamp=1469691921
    

  • 生成签名

    sign=sha256(access_token=1ba50b8f418a3ceeba989d7b789de149&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&name=alask&remark=传参示例&timestamp=1469691921)
    计算结果为:b4463c7b809416fc30640ec8ffca2ab95f80584c96f731d9ec80119b5cfebdf8
    开发者可以用这个示例检查自己的sha256算法是否有效
    

  • java签名代码如下:

    import org.apache.commons.codec.digest.DigestUtils;
    
    import java.util.Iterator;
    import java.util.Map.Entry;
    import java.util.TreeMap;
    
    public class Signs {
        public static void main(String[] args) {
            //公共参数
            String accessToken = "1ba50b8f418a3ceeba989d7b789de149";
            int timeStamp = 1469691921;
            String grantType = "client_credential";
    
            //私有参数
            String name = "alask";
            String remark = "传参示例";
    
            //密钥
            String appSecret = "f4cc82386a1cdddcc98e4f53b1115a62";
    
            //使用TreeMap会自动将key按照字典升序排列
            TreeMap<String, Object> params = new TreeMap();
            params.put("access_token", accessToken);
            params.put("grant_type", grantType);
            params.put("timestamp", timeStamp);
            params.put("name", name);
            params.put("remark", remark);
            params.put("appsecret", appSecret);
            StringBuilder stringBuilder = new StringBuilder();
            Iterator tmp = params.entrySet().iterator();
    
            while (tmp.hasNext()) {
                Entry<String, Object> entry = (Entry) tmp.next();
                stringBuilder.append(((String) entry.getKey()).trim());
                stringBuilder.append("=");
                stringBuilder.append(entry.getValue().toString().trim());
                stringBuilder.append("&");
            }
    
            //移除最后拼接的&符号
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
    
            String signContent = stringBuilder.toString();
            System.out.println("打印签名字符串:" + signContent);
    
            //256签名转16进制
            String sign = DigestUtils.sha256Hex(signContent);
            System.out.println("签名结果sign:" + sign);
    
        }
    }
    
    
    运行结果:
    打印签名字符串:access_token=1ba50b8f418a3ceeba989d7b789de149&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&name=alask&remark=传参示例&timestamp=1469691921
    签名结果sign:b4463c7b809416fc30640ec8ffca2ab95f80584c96f731d9ec80119b5cfebdf8
    

json传参业务签名示例

  • 假设公共参数如下:
    access_token:1ba50b8f418a3ceeba989d7b789de149
    timestamp:1469691921
    grant_type:client_credential
    
  • 假设私有参数json如下:

    [
      {
        "name":"alask1",
        "remark":"传参示例1"
      }, 
      {
        "name":"alask2",
        "remark":"传参示例2"
      }
    ]
    

  • 假设appsecret如下

    appsecret:f4cc82386a1cdddcc98e4f53b1115a62
    

  • 将上述json中数据在本地以_body参数参与到私有参数中做排序和签名

  • 对上述所有参数进行字典升序排列。排好序的参数信息依次为

    _body:[{"name":"alask1","remark":"传参示例1"},{"name":"alask2","remark":"传参示例2"}]
    access_token:1ba50b8f418a3ceeba989d7b789de149
    appsecret:f4cc82386a1cdddcc98e4f53b1115a62
    grant_type:client_credential
    timestamp:1469691921
    

  • 以&拼接排好序的参数,参数的形式为key=value,拼接结果如下

    _body=[{"name":"alask1","remark":"传参示例1"},{"name":"alask2","remark":"传参示例2"}]&access_token=1ba50b8f418a3ceeba989d7b789de149&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&timestamp=1469691921
    

  • 生成签名

    sign=sha256(_body=[{"name":"alask1","remark":"传参示例1"},{"name":"alask2","remark":"传参示例2"}]&access_token=1ba50b8f418a3ceeba989d7b789de149&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&timestamp=1469691921)
    计算结果为:8abb42eb9c342063a01f1cc2ea3cafe0cce5a53efd44d51ea0a72a9e82b97b69
    开发者可以用这个示例检查自己的sha256算法是否有效
    

  • json格式传参时,注意不需要将_body参数传递,只需要把私有参数放在json体中即可,公共参数放在queryString或者表单中都可以

  • java签名代码如下:

    import com.alibaba.fastjson.JSONArray;
    import org.apache.commons.codec.digest.DigestUtils;
    
    import java.util.*;
    import java.util.Map.Entry;
    
    public class Test {
        public static void main(String[] args) {
            //公共参数
            String accessToken = "1ba50b8f418a3ceeba989d7b789de149";
            int timeStamp = 1469691921;
            String grantType = "client_credential";
    
            //私有参数
            List<Map<String, Object>> dataList = new ArrayList<>();
            Map<String, Object> map1 = new HashMap<>();
            map1.put("name", "alask1");
            map1.put("remark", "传参示例1");
    
            Map<String, Object> map2 = new HashMap<>();
            map2.put("name", "alask2");
            map2.put("remark", "传参示例2");
    
            dataList.add(map1);
            dataList.add(map2);
    
            JSONArray jsonArray = new JSONArray();
            jsonArray.addAll(dataList);
    
            String _body = jsonArray.toString();
            System.out.println("打印json字符串:" + _body);
    
            //密钥
            String appSecret = "f4cc82386a1cdddcc98e4f53b1115a62";
    
            //使用TreeMap会自动将key按照字典升序排列
            TreeMap<String, Object> params = new TreeMap();
            params.put("access_token", accessToken);
            params.put("grant_type", grantType);
            params.put("timestamp", timeStamp);
            params.put("_body", _body);
            params.put("appsecret", appSecret);
            StringBuilder stringBuilder = new StringBuilder();
            Iterator tmp = params.entrySet().iterator();
    
            while (tmp.hasNext()) {
                Entry<String, Object> entry = (Entry) tmp.next();
                stringBuilder.append((entry.getKey()).trim());
                stringBuilder.append("=");
                stringBuilder.append(entry.getValue().toString().trim());
                stringBuilder.append("&");
            }
    
            //移除最后拼接的&符号
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
    
            String signContent = stringBuilder.toString();
            System.out.println("打印签名字符串:" + signContent);
    
            //sha256签名转16进制
            String sign = DigestUtils.sha256Hex(signContent);
            System.out.println("签名结果sign:" + sign);
    
        }
    }
    
    运行结果:
    打印json字符串:[{"name":"alask1","remark":"传参示例1"},{"name":"alask2","remark":"传参示例2"}]
    打印签名字符串:_body=[{"name":"alask1","remark":"传参示例1"},{"name":"alask2","remark":"传参示例2"}]&access_token=1ba50b8f418a3ceeba989d7b789de149&appsecret=f4cc82386a1cdddcc98e4f53b1115a62&grant_type=client_credential&timestamp=1469691921
    签名结果sign:8abb42eb9c342063a01f1cc2ea3cafe0cce5a53efd44d51ea0a72a9e82b97b69
    

请求注意事项

  • 请勿将appsecret参与到http请求传递中,它是双方保管的密钥,一旦泄露,请申请更换。

  • 传参编码统一使用UTF-8;

  • key和value的首尾请不要有空格,不然容易出现签名错误。

回到页面顶部