【kong系列八】之HMAC认证hmac-auth插件

来源:互联网 发布:mac上浏览图片的软件 编辑:程序博客网 时间:2024/06/05 03:07

HMAC认证


hmac 插件


构造签名header

Authorization: hmac username="userhmac", algorithm="hmac-sha1", headers="X-Date Content-md5", signature="LqkezHTAuk/Sk3RTbguHHYZGt/8="

X-Date: Mon, 31 Jul 2017 07:23:02 GMT

Content-md5: IgWlVHazOsGgHGVlcKvQDA==



执行结果:成功


详解:Base64(HMAC-SHA1(signing string))加密详解:

一、事先准备加密工具HmacSha1Util Md5Util

1).编写HMacSha1Util.java,参看附1内容。

2).编写Md5Util,参考附2内容。

3).准备mac用户和密钥: username=userhmacsecret=zcy@0808

二、计算hmac签名

1).计算body Content-md5.

2).构建待签名报文String content = stb.append("X-Date: ").append(hdate).append("\n").append("Content-md5: ").append(contentMD5).toString(); //注意 X-Date:后有一个空格,紧接着才是US GMT时间。

3).构建签名String signature = BASE64.encode(HmacSha1Util.signatureReturnBytes(content, secret));

详细请参看附3 HmacTest.java

根据HmacTest.test1()方法执行的结果输出:

15:25:07.774 [main] INFO  com.kong.test.hmac.HmacTest - Content-md5: IgWlVHazOsGgHGVlcKvQDA==

15:25:07.793 [main] INFO  com.kong.test.hmac.HmacTest - X-Date: Mon, 31 Jul 2017 07:25:07 GMT

15:25:07.794 [main] INFO  com.kong.test.hmac.HmacTest -签名前内容: X-Date: Mon, 31 Jul 2017 07:25:07 GMT

Content-md5: IgWlVHazOsGgHGVlcKvQDA==

15:25:08.557 [main] INFO  com.kong.test.hmac.HmacTest -显示指定编码[推荐]: p4sGy3B+J/Zqt7gaLJVZCzVY5/Y=

将以上内容输出结果,按下文格式构建request报文。

三、构建request报文:

设置headers

Authorization:hmac username="userhmac", algorithm="hmac-sha1", headers="X-Date Content-md5", signature="p4sGy3B+J/Zqt7gaLJVZCzVY5/Y="

X-Date:Mon, 31 Jul 2017 07:25:07 GMT

Content-md5:IgWlVHazOsGgHGVlcKvQDA==


四、验证结果

如下图,正常返回,hamc加密认证成功。




1 HmacSha1Util.java

package com.kong.test.hmac;import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.util.Formatter;/** * @Author changle * @Time 17/7/23. * @Desc 计算hmac签名 */public class HmacSha1Util {    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";    private static String toHexString(byte[] bytes) {        Formatter formatter = new Formatter();        for (byte b : bytes) {            formatter.format("%02x", b);        }        return formatter.toString();    }    public static String signature(String data, String key) throws NoSuchAlgorithmException, InvalidKeyException {        SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);        Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);        mac.init(signingKey);        return toHexString(mac.doFinal(data.getBytes()));    }    public static byte[] signatureReturnBytes(String data, String key) throws NoSuchAlgorithmException, InvalidKeyException {        SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);        Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);        mac.init(signingKey);        return mac.doFinal(data.getBytes());    }    public static void main(String[] args) throws Exception {        String hmac = signature("data", "f96384947e0f4de39d3ffef6bd12c551");        assert hmac.equals("104152c5bfdca07bc633eebd46199f0255c9f49d");    }}



2 Md5Util.java

package com.kong.test.hmac;import org.apache.commons.codec.binary.Base64;import org.apache.commons.lang.StringUtils;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;public class Md5Util {    public static String md5(String param) {        if (StringUtils.isBlank(param)) {            throw new IllegalArgumentException("param can not be null");        }        try {            byte[] bytes = param.getBytes("utf-8");            final MessageDigest md = MessageDigest.getInstance("MD5");            md.reset();            md.update(bytes);            final Base64 base64 = new Base64();            final byte[] enbytes = base64.encode(md.digest());            return new String(enbytes);        } catch (final NoSuchAlgorithmException e) {            throw new IllegalArgumentException("unknown algorithm MD5");        } catch (UnsupportedEncodingException e) {            throw new RuntimeException(e);        }    }}



3 HmacTest.java 计算mac签名:

package com.kong.test.hmac;import lombok.extern.slf4j.Slf4j;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Base64;import java.util.Date;import java.util.Locale;import java.util.TimeZone;/** * @Author changle * @Time 17/7/19. * @Desc HMac加密签名验证. */@Slf4jpublic class HmacTest {    public static void main(String[] args) {        test1();    }    static void test1(){        String queryParam = "/testHmac/qryParam=test1&pageNo=1";        String contentMD5 = Md5Util.md5(queryParam);        log.info("Content-md5: {}", contentMD5);        Date d=new Date();        DateFormat format=new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);        format.setTimeZone(TimeZone.getTimeZone("GMT"));        String hdate = format.format(d);        log.info("X-Date: {}",hdate);        StringBuilder stb = new StringBuilder();        String content = stb.append("X-Date: ").append(hdate).append("\n").append("Content-md5: ").append(contentMD5).toString();        log.info("签名前内容: "+content);        String secret = "zcy@0808";  //用户userhmac的密钥        try {            String signature2 = new String(Base64.getEncoder().encode(HmacSha1Util.signatureReturnBytes(content, secret)), "US-ASCII");            log.info("显示指定编码[推荐]: {}", signature2);        } catch (Exception e) {            e.printStackTrace();        }    }}