Kong HMAC认证对接

HMAC

HMAC是一种利用密码学中的散列函数来进行消息认证的一种机制,所能提供的消息认证包括两方面内容:

①消息完整性认证:能够证明消息内容在传送过程没有被修改。

②信源身份认证:因为通信双方共享了认证的密钥,接收方能够认证发送该数据的信源与所宣称的一致,即能够可靠地确认接收的消息与发送的一致。

HMAC是当前许多安全协议所选用的提供认证服务的方式,应用十分广泛,并且经受住了多种形式攻击的考验。

HMAC与一般的加密重要的区别在于它具有“瞬时"性,即认证只在当时有效,而加密算法被破解后,以前的加密结果就可能被解密。

Kong配置

请求参数

参数说明

需要增加2个request header:

  • Date:当前时间(为了方便对接,开发阶段此值设定为距当前时间1小时内),GMT格式,与北京时间相差8小时。例:Sat, 10 Oct 2020 08:10:21 GMT。(该参数除了用于参与签名计算,更重要的作用是防止重复攻击。假设抓包到了请求数据,包含当前日期以及认证信息,如果该日期没有时间限制,就可以一直重复使用)
  • Authorization:hmac username="app", algorithm="hmac-sha256", headers="date request-line", signature="Vr7f7g6dzwxW6bP7dSiJutyOm8aiJl+IG5XJqyOHERU=",其中username的值由网关给出,signature为Base64编码后的签名,其余固定。

签名算法

使用HMAC-SHA256加密算法,参数为message和secret。secret由网关给出。伪代码描述:

  message="date: Thu, 22 Jun 2017 17:15:21 GMT\nGET /requests HTTP/1.1"
  secret="secret"
  digest=HMAC-SHA256(message, secret)
  base64_digest=base64(digest)

message格式:

  • 如果request header的name不是request-line,追加小写的header name,追加冒号和空格,追加值。比如date: Thu, 22 Jun 2017 17:15:21 GMT
  • 如果是request-line,追加HTTP request line
  • 多个request header中间使用\n隔开。

message参数:

  • Date:客户端增加的参数,见参数说明,符合message格式的第一条,注意冒号和值之间有一个空格。
  • Request-Line:Request-Line=Method空格Request-URI空格HTTP-Version。例如:GET /request?a=11&b=22 HTTP/1.1
  • Request-URI:上面Request-Line的一部分,the path with the querystring。例如:url为 https://example.com:1234/v1/movies?movie=foo,则Request-URI=/v1/movies?movie=foo

完整的message示例:date: Thu, 22 Jun 2017 17:15:21 GMT\nGET /request?a=11&b=22 HTTP/1.1

举个例子

假设有GET请求接口地址为:http://kong.alicontainer.com/app/hot

Date为:Sat, 15 Oct 2020 07:40:21 GMT

则message为:date: Sat, 15 Oct 2020 07:40:21 GMT\nGET /app/hot HTTP/1.1

signature为:cCUTMy/11ZkyAtp+iSh1/BftKJODibZQgf4Oi8q/d9o=

异常说明

http status:401

  1. header中没有date参数,或者date时间不合法(距当前时间5分钟内,gmt格式,与北京时间差8小时)

    { "message": "HMAC signature cannot be verified, a valid date or x-date header is required for HMAC Authentication"}
    
  2. 签名错误

    {  "message": "HMAC signature does not match"}
    

客户端实现

客户端当根据自己的环境使用拦截器思想,在请求即将发出前统一拦截,在header中增加认证参数,以下仅给出获取计算signature的代码示例。

Java版本

  /**
     * 获取当前GMT format 时间
     *
     * @return
     */
    public static String getGMTTime() {
        DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        return dateFormat.format(Calendar.getInstance().getTime());
    }
public static String sign(String secret, String message) {
    try {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        mac.init(secretKey);
        return Base64.encodeBase64String(mac.doFinal(message.getBytes()));
    } catch (NoSuchAlgorithmException | InvalidKeyException e) {
        throw new IllegalArgumentException("签名错误:" + e.getMessage());
    }
}
public static void main(String[] args) {
    String secret = "dapeng";
    String message = "date: Sat, 10 Oct 2020 08:10:21 GMT\nGET /mock?a=1 HTTP/1.1";
    String sign = sign(secret, message);
    System.out.println(sign);//Vr7f7g6dzwxW6bP7dSiJutyOm8aiJl+IG5XJqyOHERU=
}
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>

body验证

body数据签名验证需要增加另一个header:Digest,value为:Digest: SHA-256=base64(sha256(<body>)),例如:SHA-256=RgecWaKvMqh5T79Ps93OuyZ5CZuPnZ6dTgsh5i9xJUs=

将body字符串使用sha256加密,再使用base64编码,这里不涉及secret。

java版本:

public static String String2SHA256(String str) {
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        byte[] hash = messageDigest.digest(str.getBytes());
        return Base64.encodeBase64String(hash);
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("签名错误:" + e.getMessage());
    }
}
public static void main(String[] args) {
    Map<String, String> map = new HashMap<>(1);
    map.put("name", "123");
    String body = JSON.toJSONString(map);
    System.out.println(String2SHA256(body));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章