API参数如何进行摘要签名验证的?

esolve
  • 948

假设A开发了一系列API,要求调用这些API的调用者对调用参数进行签名,然后A在后台对每个请求的签名进行验证。

假设B要调用这些API,首先需要将参数序列化为json,然后对json string进行md5算法运算,得到签名sig

A收到B调用api的request,取出参数,记性呢md5运算,然后和sig对比。但是A取出的参数json string需要和B当时得到的一致。

可是由于json序列化可能导致json各kv对的顺序变化,这种一致性就难以保证。

另一种方法是从request请求中将字节读出来,直接用md5对字节流进行运算处理。不过这样的话,一般这个动作发生在interceptor中,字节读出来后怎么放回去让接下来的Controller读到参数呢?这又是问题。

回复
阅读 2.8k
2 个回答

不需要对所有请求参数进行签名啊。kong网关的hmac-auth插件认证流程,感觉挺符合你的要求。他的思路是分发一个username和secret给调用者,然后调用者需要附加一些特定的请求头,并指定一个摘要方法(这个方法名称也会在header中体现)把这些请求头用密钥签名,服务器拿到请求后,根据username去查找对应的secret,并对请求的签名进行验证。
简述一下kong hmac-auth的流程

  1. 分发 usernamesecret给第三方应用
  2. 第三方请求你的api 资源,例:

     POST http://example.com/restapi
    1. 构造需要签名的字符串(可以指定任何格式的字符串,只要是需要签名的字符串对双方都可见),如"<date> <request-line>", 如"date: Fri, 20 Sep 2019 22:10:02 GMT\nPOST /restapi HTTP/1.1"(使用date可以防重放攻击,统一使用gmt-0市时区)
    2. 指定签名方法,如hmac-sha1,使用分发的密钥对上述字符串提取摘要digest,并使用Base64进行转义为最终的base64_digest

      signing_string="date: Fri, 20 Sep 2019 22:10:02 GMT\nPOST /restapi HTTP/1.1"
      digest=HMAC-SHA1(<signing_string>, "secret")
      base64_digest=base64(<digest>)
    3. 调用方构建请求头,格式如下

      curl -X POST http://example.com/restapi
         -H 'Date: Fri, 20 Sep 2019 22:10:02 GMT'
         -H 'Authorization: username=<username> algorithm="hmac-sha1" signature="<bas64_digest>"'
         -d '{...}'
    4. 服务器使用JAVA代码重复上面过程进行签名, 如果请求的date对比服务器时间在允许的误差内,比如说5秒内,则进行签名验证,如果大于5秒直接报错。根据请求的username在数据库中查找secret, 以同样的流程进行签名认证

Kong hmac-plugin官方网站
Github kong hmac java认证字符串生成(引用下别人的代码)

1、一般是根据参数名称的ASCII码表的顺序排序,将排序好的参数名和参数值拼装在一起,然后使用MD5或者HMAC算法来签名sign
2、字节读出来后怎么放回去?--> 如果是使用spring mvc的话,用ContentCachingRequestWrapper就可以

宣传栏