在 go-zero
负责通过签名来验证请求是否合法的中间件:contentsecurityhandler
params | 参数说明 |
---|---|
fingerprint | 指纹字符串 |
publicKey | 公钥 |
privateKey | 私钥 |
key | 私钥密码 |
engine.AddRoute(rest.Route{
Method: http.MethodGet,
Path: "/",
Handler: handle,
},rest.WithSignature(rest.SignatureConf{
Strict: true, // 是否严格模式
Expiry: time.Hour, // 允许的最大时间跨度
PrivateKeys: []rest.PrivateKeyConf{
rest.PrivateKeyConf{
Fingerprint: "", // your Fingerprint
KeyFile: "", // your PrivateKey
},
},
}))
engine := rest.MustNewServer(c.RestConf,rest.WithUnsignedCallback(func(w http.ResponseWriter, r *http.Request, next http.Handler, strict bool, code int) {
// your own custom callback function
}))
需要在http header中设置 X-Content-Security 值为 key=yourFingerprint;secret=yourSecret;signature=yourSignature
r.Header.Set("X-Content-Security", strings.Join([]string{
fmt.Sprintf("key=%s", fingerprint),
fmt.Sprintf("secret=%s", secret),
fmt.Sprintf("signature=%s", signature),
}, "; "))
取值为密钥参数中的 fingerprint 值
secret 生成规则
//1.将以上三个值以;分割
content := strings.Join([]string{
fmt.Sprintf("type=%s", mode),
fmt.Sprintf("key=%s", base64.StdEncoding.EncodeToString(key)), //对私钥密码做base64加密
fmt.Sprintf("time=%s", strconv.FormatInt(time.Now().Unix(), 10)),
}, "; ")
//用公钥对所得字符串进行rsa加密取base64值
encrypter, _ := codec.NewRsaEncrypter([]byte(pubKey))
output, _ := encrypter.Encrypt([]byte(content))
secret := base64.StdEncoding.EncodeToString(output)
signature 生成规则
//1.按timestamp,method,path,query,bodySign的顺序 以换行(\n)分割成字符串
str := strings.Join([]string{
"1602745942",
"POST",
"/a/b",
"c=d&e=f",
"49adb43b1c44f36c046357da1ff548d739e89c8cc75cbe4536752c476dad0761"
}, "\n")
func Hmac(key []byte, body string) []byte {
h := hmac.New(sha256.New, key)
io.WriteString(h, body)
return h.Sum(nil)
}
func HmacBase64(key []byte, body string) string {
return base64.StdEncoding.EncodeToString(Hmac(key, body))
}
//2.然后再将此字符串用你的key做hmac后再base64加密
sign:= HmacBase64("yourKey",str)
/**
* 签名
* @param {*} url 相对路径的地址
* @param {*} query url 参数
* @param {*} method 请求方式
* @param {*} data 请求体
*/
var httpSign = function (url, query, method, data) {
// 随机生成秘钥
var key = uuid.v4();
// 请求体要是string
var newData = typeof data === 'string' ? data : JSON.stringify(data);
// 拿到当前时间戳
var timestamp = Date.parse(new Date().toString()) / 1000;
// 对请求体做 sha256 加密
var hexString = sha256(newData);
var signatureData = [timestamp.toString(), method.toUpperCase(), url, query, hexString];
var secretData = ["version=" + version, "type=0", "key=" + base64Encode(key), "time=" + timestamp];
// 使用公钥对 secretData 以;分割的字符串进行 rsa 加密
var secret = rsaEncrypt(secretData.join(';'), PublicKey);
// 对signatureData 以 \n 分割的字符串先hmac在进行 sha256 加密
var signature = hmacSHA256(signatureData.join('\n'), key);
// res 就是所得的放在请求头 X-Content-Security 中的签名字符串
var res = "key=" + fingerprint + ";secret=" + secret + ";signature=" + signature;
return res;
};