微服务网关密钥对鉴权

最近更新时间:2020-02-13 11:58:40

HTTP 请求头

HTTP 请求头中各参数说明如下:

名称 位置 是否必选 说明
x-mg-traceid 请求/响应 请求响应 ID,用于跟踪异常请求调用。
x-mg-secretid 请求 授权的 SecretID,用于加签。开启密钥对鉴权时需要。
x-mg-alg 请求/响应 加密算法。开启密钥对鉴权时需要。
0:hmac_md5
1:hmac_sha_1
2:hmac_sha_256
3:hmac_sha_512
x-mg-sign 请求/响应 签名值。开启密钥对鉴权时需要。
x-mg-nonce 请求/响应 随机数。开启密钥对鉴权时需要。
x-mg-code 响应 响应码。

签名算法

算法列表

  • Hmac_MD5
  • HMAC_SHA_1
  • HMAC_SHA_256
  • HMAC_SHA_512

生成规则

  • digetValue = (x-mg-noce)+secretId+secretKey
  • signValue = Base64String(签名算法(secretKey, digetValue ),"utf-8")

案例说明

签名算法: hmac_md5
secretId: hKhATL/DHVXXXXgeROMrrQ==
secretKey: +t9tTMTXXXXUcE+RKOleg==
x-mg-noce: D7pAR5fqXXXXx1yacuVzdO
digetValue: D7pAR5fqXXXXx1yacuVzdOhKhATL/DHVXXXXgeROMrrQ==+t9tTMTXXXXXUcE+RKOleg==
signValue: FE6nLWwYBDXXXXU2CVtFndUBoyg=

校验规则

将请求头中的 x-mg-sign 与服务端根据签名生成规则计算的 signValue 进行比对,判断是否通过鉴权。

代码实现

Java 代码:

   /**
     * 生成签名
     *
     * @param nonce 随机字符串
     * @param secretId 密钥 ID
     * @param secretKey 密钥值
     * @param algType 签名算法 {@link AlgType}
     */
    public static String generate(String nonce, String secretId, String secretKey, AlgType algType) {
        String digestValue = nonce + secretId + secretKey;
        byte[] serverSignBytes;
        switch (algType) {
            case HMAC_MD5:
                serverSignBytes = HmacUtils.hmacMd5(secretKey, digestValue);
                break;
            case HMAC_SHA_1:
                serverSignBytes = HmacUtils.hmacSha1(secretKey, digestValue);
                break;
            case HMAC_SHA_256:
                serverSignBytes = HmacUtils.hmacSha256(secretKey, digestValue);
                break;
            case HMAC_SHA_512:
                serverSignBytes = HmacUtils.hmacSha512(secretKey, digestValue);
                break;
            default:
                throw new UnsupportedException("不支持的鉴权算法: " + algType);
        }
        String signValue = Base64.encodeBase64String(serverSignBytes);
        if (logger.isDebugEnabled()) {
            logger.debug("签名明文:{},签名密文:{}", digestValue, signValue);
        }
        return signValue;
    }

    public static void main(String[] args) {
        String secretId = "hKhATL/DHVXXXXgeROMrrQ==";
        String secretKey = "+t9tTMTXXXXUcE+RKOleg==";
        String nonce = "D7pAR5fqXXXXx1yacuVzdO";
        AlgType algType = AlgType.HMAC_SHA_1;
        System.out.println(SignUtil.generate(nonce, secretId, secretKey, algType));
    }


Python 代码:

# -*- coding: utf-8 -*-
"""
     使用SHA1算法生成签名,入参为 SecretId 和 SecetKey
"""
import sys
from hashlib import sha1
import string
import random
import hmac
import base64
import uuid
seed=['1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
nonce=string.join(random.sample(seed,22)).replace(" ","")
signstr=nonce+sys.argv[1]+sys.argv[2]
local_sign_seed = hmac.new(sys.argv[2],signstr , sha1).digest()
sign = base64.b64encode(local_sign_seed)
print ""
print "generate local sign: " +sign
print ""
print "=== http request headers as followed === "
print "x-mg-nonce: "+nonce
print "x-mg-secretid: "+sys.argv[1]
print "x-mg-traceid: "+str(uuid.uuid1())
print "x-mg-alg: 1"
print "x-mg-sign: "+sign

使用说明

生成签名

使用上面 Python 代码 生成签名,文件命名为:gen_sign.py。

python gen_sign.py {secretId} {secretKey}

{secretId} 替换成密钥 ID,{secretKey} 替换成密钥 KEY,示例如下:

python gen_sign.py hKhATL/DHVXXXXgeROMrrQ==  +t9tTMTXXXXUcE+RKOleg==

输出内容:

generate local sign: FE6nLWwYBDXXXXU2CVtFndUBoyg=
=== http request headers as followed === 
x-mg-nonce: D7pAR5fqXXXXx1yacuVzdO
x-mg-secretid: hKhATL/DHVXXXXgeROMrrQ==
x-mg-traceid: 8a237eba-71b2-11e9-acee-5254001d2da0
x-mg-alg: 1
x-mg-sign: FE6nLWwYBDXXXXU2CVtFndUBoyg=

curl 方式测试

  • 测试无鉴权的 API:
    curl -X {GET}  -H 'x-mg-traceid:71b2-11e9-acee-5254001-8a237eba'  http://{gatewayIp}:{gatewayPort}/{groupContext}/{namespaceName}/{serviceName}/{apiPath}
  • 测试鉴权的 API:
    curl -X {POST} -H 'content-type: application/json;charset=utf-8' -H 'x-mg-secretid:{secretid}' -H 'x-mg-sign: {sign}' -H 'x-mg-nonce: {nonce}'  -H 'x-mg-alg:1'  -H 'x-mg-traceid:71b2-11e9-acee-5254001-8a237eba' -d '{具体的报文}' http://{gatewayIp}:{gatewayPort}/{groupContext}/{namespaceName}/{serviceName}/{apiPath}
说明:

{ } 中的参数请根据实际内容替换。