全部产品

后端签名校验说明

更新时间:2019-09-09 11:37:54

移动网关提供服务端 HTTP 服务签名验证功能,提高从网关到服务端的数据安全性。

  • 在网关控制台开启某一 API 分组的签名校验后,移动网关会对该分组里面的每一个 API 请求创建签名信息,签名使用的公私钥可在网关控制台创建;
  • 服务端读取签名字符串后,对收到的请求进行本地签名计算,比对与收到的签名是否一致,以此来判断请求是否合法。

读取签名

移动网关计算的签名保存在 Request 的 Header 中,Header Key 为 X-Mgs-Proxy-Signature

API 分组中配置的 密钥 Key 可用来区分和获取不同的密钥值对应的 Key,Header Key 为 X-Mgs-Proxy-Signature-Secret-Key

验签方法

组织加签数据

  1. String stringToSign =
  2. HTTPMethod + "\n" +
  3. Content-MD5 + "\n" +
  4. Url
  • HTTPMethod:全大写的 HTTPMethod,如 PUTPOST 等。

  • Content-MD5:请求 Body 的 MD5 值。计算方法如下:

    1. 若 HTTPMethod 非 PUT 或 POST 之一,则 MD5 为空字符串 "";否则执行第二步。
    2. 若请求有 Body 且 Body 为 Form 表单,则 MD5 为空字符串 "";否则执行第三步。
    3. 使用以下方式计算 MD5。其中,当请求无 Body 时,bodyStream 为字符串 "null"
      1. String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes(“UTF-8”)));

      重要:即使 content-MD5 为空字符串 "",加签方法中 content-MD5 后面的换行符 “\n” 也不能省略,即此时签名中会有连续两个 “\n”。

  • Url:由 Path、Query 以及 Body 中的 Form 参数组装而成。假设请求格式为 http://ip:port/test/testSign?c=3&a=1 且 Form 中的参数为 b=2&d=4,组装步骤如下:

    1. 获取 Path:Path 是 ip:port 之后、? 之前的部分。此例中即为 /test/testSign
    2. 若请求 Query 和 Form 参数均为空,则 Url 即为 Path;否则进行下一步。
    3. 拼接参数:将 Query 和 Form 中的参数根据 Key 按照字典序排序,然后拼接为 Key1=Value1&Key2=Value2&...&KeyN=ValueN。此例中即为 a=1&b=2&c=3&d=4

      重要:Query 或 Form 参数的 Value 可能有多个,只取第一个 Value 即可。

    4. 拼接 Url:Url 为 Path?Key1=Value1&Key2=Value2&...&KeyN=ValueN。此例中即为 /test/testSign?a=1&b=2&c=3&d=4

验证签名

  • 采用 MD5 算法验签
  1. String sign = "xxxxxxx";//移动网关传过来的签名
  2. String salt ="xxx"; //MD5 Salt
  3. MessageDigest digest = MessageDigest.getInstance("MD5");
  4. String toSignedContent = stringToSign + salt;
  5. byte[] content = digest.digest(toSignedContent.getBytes("UTF-8"));
  6. String computedSign = new String(Hex.encodeHexString(content));
  7. boolean isSignLegal = sign.equals(computedSign) ? true : false;
  • 采用 RSA 算法验签
  1. String sign = "xxxxxxx"; //移动网关传过来的签名
  2. String publicKey ="xxx"; //移动网关的 RSA 公钥
  3. PublicKey pubKey = KeyReader.getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));
  4. java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA");
  5. signature.initVerify(pubKey);
  6. signature.update(stringToSign.getBytes("UTF-8"));
  7. boolean isSignLegal = signature.verify(Base64.decodeBase64(sign.getBytes(""UTF-8"")));