JAVA 使用摘要签名认证方式调用阿里网关API

场景:老板突然一个需求发到我,需要将分销商的扫码内容解码获取到真实的商品条码(由于分销商使用了阿里的数据转换API服务,所以要解码)

一、调用阿里API的方式文档地址

1.使用简单认证(AppCode)方式调用API

2.使用SDK调用API

3.使用摘要签名认证方式调用API(本篇主要讲这个方式)

二、生成签名

1.准备API的 AppKey、AppSecret

2.客户端生成签名一共分三步处理:

2.1.从下面7个字段构成整个签名串,字段之间使用\n间隔换行,如果Headers为空,则不需要加\n,其他字段如果传空则必须要保留\n(关键点)

HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters
  • HTTPMethod:HTTP的方法,全部大写,比如POST
  •  Accept:请求中的Accept头的值,可为空,可传
    application/json; charset=utf-8
  • Content-MD5:请求中的Content-MD5头的值,可为空
  • Content-Type:请求中的Content-Type头的值,可为空,可传
    application/x-www-form-urlencoded; charset=UTF-8
  • Date:请求中的Date头的值,可为空
  • Headers:用户可以选取指定的header参与签名,关于header的签名串拼接方式有以下规则:参与签名计算的Header的Key按照字典排序后使用如下方式拼接:
    HeaderKey1 + ":" + HeaderValue1 + "\n" +
    HeaderKey2 + ":" + HeaderValue2 + "\n" +
    ...
    HeaderKeyN + ":" + HeaderValueN + "\n"

       某个Header的Value为空,则使用HeaderKey+":"+"\n"参与签名,需要保留Key和英文冒号

       所有参与签名的Header的Key的集合使用英文逗号分割放到Key为X-Ca-Signature-Headers的  Header中

以下Header不参与Header签名计算:X-Ca-Signature、X-Ca-Signature-Headers、Accept、Content-MD5、Content-Type、Date;

  • PathAndParameters这个字段包含Path,Query和Form中的所有参数,具体组织形式如下:
Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN

Query和Form参数对的Key按照字典排序后使用上面的方式拼接;

Query和Form参数为空时,则直接使用Path,不需要添加?;

参数的Value为空时只保留Key参与签名,等号不需要再加入签名;

Query和Form存在数组参数时(key相同,value不同的参数) ,取第一个Value参与签名计算。

2.2.使用HmacSHA256加密算法加AppSecret 对签名字符串进行加密处理,得到签名

3.将签名字符串所相关的所有头加入到原始HTTP请求中,得到最终HTTP请求

三、不废话 上代码

1.准备工作

//阿里API AppKey
    public final static String appKey = "xxxxx";
    //阿里API AppSecret
    public final static String appSecret = "xxxxxxxxx";
    //请求参数
    public final static String queryParams = "xxxxxxx";
    //阿里API
    public final static String ALiBaBaApi = "https://api.ailend.top/api/v1x/xxxxx/xxxxxx?x="+queryParams;
    //签名串的7个字段
    public final static String HTTPMethod = "POST";
    public final static String Accept = "application/json; charset=utf-8";
    public final static String Content_MD5 = "";
    public final static String Content_Type = "application/x-www-form-urlencoded; charset=UTF-8";
    public final static String Date = "";
    public final static String Headers = "X-Ca-Key:%s" +"\n"+
                                        "X-Ca-Nonce:%s"  +"\n"+
                                        "X-Ca-Signature-Method:HmacSHA256" +"\n"+
                                        "X-Ca-Timestamp:%s";
    public static String PathAndParameters = "";

2.组装签名串

/*
     * 组装签名串
     * @params uuid 随机数
     * @params url 请求的阿里API
     * @params timestamp 时间戳
     * */
    public static String packageSignStr(String uuid,String url,long timestamp){
        URL parseUrl = URLUtil.url(url);
        PathAndParameters = parseUrl.getPath()+"?"+parseUrl.getQuery();
        String temp = HTTPMethod +"\n"+
                    Accept +"\n"+
                    Content_MD5 +"\n"+
                    Content_Type +"\n"+
                    Date +"\n"+
                    Headers +"\n"+
                    PathAndParameters;
        return String.format(temp,appKey, uuid, timestamp);
    }

3.生成签名的方法

/*
    * 生成加密签名
    * @params content 组装好的签名串
    * @params appSecret 密钥
    * */
    private static String getSHA256StrJava(String content, String appSecret) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(StrUtil.bytes(appSecret, CharsetUtil.UTF_8), "HmacSHA256");
        mac.init(secret_key);
        byte[] binaryData = mac.doFinal(StrUtil.bytes(content, CharsetUtil.UTF_8));
        return Base64.getEncoder().encodeToString(binaryData);
    }

 4.调用生成

String uuid = UUID.randomUUID().toString();
long l = System.currentTimeMillis();
//生成签名
String sign = getSHA256StrJava(packageSignStr(uuid, ALiBaBaApi,l),appSecret);
//请求头加入签名
String body = HttpUtil.createPost(ALiBaBaApi)
                .header("Accept", "application/json; charset=utf-8")
                .header("Content-MD5", "")
                .header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                .header("Date", "")
                .header("X-Ca-Key", appKey)
                .header("X-Ca-Nonce", uuid)
                .header("X-Ca-Signature-Method", "HmacSHA256")
                .header("X-Ca-Timestamp", String.valueOf(l))
                .header("X-Ca-Signature-Headers", "X-Ca-Key,X-Ca-Nonce,X-Ca-Signature-Method,X-Ca-Timestamp")
                .header("X-Ca-Signature", sign)
                .execute().body();
System.out.println("requestRes : "+body);

四、签名排错

当签名不匹配时网关会通过 HTTP Response Header 中的 X-Ca-Error-Messaqe 返回服务端参与签名计算的 StringToSign.

我们只需要打印出 packageSignStr() 方法生成的签名串 ,然后与响应头中的 X-Ca-Error-Messaqe 中值进行比对即可,找出哪里不同,针对性解决就OK了,多一个字符、少一个字符、多一个换行、少一个换行都会返回签名无效,注意:响应头中的#为换行符\n

如果服务端与客户端的StringToSign一致请检查用于签名计算的APP Secret是否正确。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值