# 签名生成

> 来源：https://help.gravity-engine.com/docs/server-integration/request-signing
> 说明 Gravity Engine OpenAPI 的 sign 与 Authorization 生成步骤，并提供 Java、Go 和 Python 示例代码。





调用引力服务端 openapi 接口时，部分接口需要 `Authorization` 和 `sign` 字段，本文主要给出示例，我们提供了以下 Java、Golang 和 Python 版本的示例，请参照示例生成签名。

主要分为两个方法：

1. 获取 sign
2. 获取 Authorization

现分别介绍如下。

## 1. 获取 sign [#1-获取-sign]

获取 `sign` 时，先组装 `params` 参数，参数为接口除了 `sign` 字段之外的其他所有字段的字典集合，组装完成后，调用 `getSign` 方法获取 sign 字符串。

> 针对 params 参数，不同的接口有不同的要求，具体请参考各个接口说明文档。

## 2. 获取 Authorization [#2-获取-authorization]

使用上一步获取的 `sign` 和 `app_key`，调用 `getAuthorization` 方法获取 `Authorization` 字符串，其中 `app_key` 为您申请的开发者应用的 key，您可以在[引力后台-设置-引力开发者](https://web.gravity-engine.com/#/manage/develop)中查看。

## 3. 代码示例 [#3-代码示例]

<Tabs items="['Java', 'Golang', 'Python']">
  <Tab value="Java">
    ```java
    package com.example;

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    import com.alibaba.fastjson2.JSONObject;
    import com.alibaba.fastjson2.JSONWriter;
    import com.google.common.base.Charsets;
    import com.google.common.base.Joiner;
    import com.google.common.collect.Maps;
    import com.google.common.hash.Hashing;
    import cn.hutool.jwt.JWTUtil;
    import cn.hutool.jwt.signers.JWTSigner;
    import cn.hutool.jwt.signers.JWTSignerUtil;

    /**
     * 引力引擎签名工具类
     */
    public class SignUtil {

        /**
         * 字符串转Unicode编码
         * @param string 原始字符串
         * @return Unicode编码字符串
         */
        public static String string2Unicode(String string) {
            StringBuffer unicode = new StringBuffer();
            for (int i = 0; i < string.length(); i++) {
                char c = string.charAt(i);
                if (c < 0x20 || c > 0x7E) {
                    String tmp = Integer.toHexString(c);
                    if (tmp.length() >= 4) {
                        unicode.append("\\u" + Integer.toHexString(c));
                    } else if (tmp.length() == 3) {
                        unicode.append("\\u0" + Integer.toHexString(c));
                    } else if (tmp.length() == 2) {
                        unicode.append("\\u00" + Integer.toHexString(c));
                    } else if (tmp.length() == 1) {
                        unicode.append("\\u000" + Integer.toHexString(c));
                    } else {
                        unicode.append("\\u0000");
                    }
                } else {
                    unicode.append(c);
                }
            }
            return unicode.toString();
        }

        /**
         * 参数加签
         * @param map 请求参数
         * @param appKey 申请的引力APPKEY
         * @return 签名字符串
         */
        public static String getSign(Map<String, Object> map, String appKey) {
            List<String> params = new ArrayList<>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                if (entry.getKey().equals("sign")) {
                    continue;
                }
                params.add(entry.getKey() + "=" + JSONObject.toJSONString(entry.getValue(), JSONWriter.Feature.MapSortField));
            }
            Collections.sort(params);
            StringBuilder sb = new StringBuilder();
            sb.append(Joiner.on("&").join(params));
            sb.append(appKey);
            String str = sb.toString().replaceAll("\"", "").replaceAll(" ", "");
            return Hashing.md5().newHasher().putString(string2Unicode(str), Charsets.UTF_8).hash().toString();
        }

        /**
         * 请求头加签
         * @param appKey 申请的引力APPKEY
         * @param sign 参数加签
         * @return Authorization 请求头签名
         */
        public static String getAuthorization(String appKey, String sign) {
            HashMap<String, Object> payload = Maps.newHashMap();
            payload.put("app_key", appKey);
            JWTSigner jwtSigner = JWTSignerUtil.hs256(sign.getBytes());
            return JWTUtil.createToken(payload, jwtSigner);
        }
    }
    ```
  </Tab>

  <Tab value="Golang">
    ```go
    package test

    import (
    	"crypto/md5"
    	"encoding/json"
    	"fmt"
    	"github.com/dgrijalva/jwt-go"
    	"sort"
    	"strings"
    )

    // asciiEscape 将非 ASCII 字符转义为 \uXXXX
    func asciiEscape(s string) string {
    	var buf strings.Builder
    	for _, r := range s {
    		if r < 128 {
    			buf.WriteRune(r)
    		} else {
    			buf.WriteString(fmt.Sprintf("\\u%04x", r))
    		}
    	}
    	return buf.String()
    }

    // 参数签名
    // @param params map[string]interface{} 参数
    // @param appKey string app key
    func getSign(params map[string]interface{}, appKey string) string {
    	paramsList := make([]string, 0)
    	for k, v := range params {
    		if k == "sign" {
    			continue
    		}
    		raw, _ := json.Marshal(v)
    		jsonString := asciiEscape(string(raw))
    		paramString := fmt.Sprintf("%s=%s", k, jsonString)
    		paramsList = append(paramsList, paramString)
    	}
    	sort.Strings(paramsList)
    	currentString := strings.ReplaceAll(strings.ReplaceAll(strings.Join(paramsList, "&")+appKey, "\"", ""), " ", "")
    	sign := fmt.Sprintf("%x", md5.Sum([]byte(currentString)))
    	return sign
    }

    // 获取请求 authorization
    // @param sign string 签名
    // @param appKey 请求key
    func getAuthorization(sign, appKey string) string {
    	type MyClaims struct {
    		AppKey string `json:"app_key"`
    		jwt.StandardClaims
    	}
    	claims := MyClaims{
    		AppKey:         appKey,
    		StandardClaims: jwt.StandardClaims{},
    	}
    	t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    	token, _ := t.SignedString([]byte(sign))
    	return token
    	}
    ```
  </Tab>

  <Tab value="Python">
    ```python
    import json
    import hashlib
    import jwt

    def get_sign(params: dict , app_key: str) -> str:
    """
    @param params: 请求参数
    @param app_key: 引力申请的开发者app_key
    """

    param_list = []
    for k, v in params.items():
        if k == "sign":
            continue
        param_list.append(f"{k}={json.dumps(v,sort_keys=True)}")
    param_list.sort()
    sb = "&".join(param_list) + app_key
    current_str = sb.replace("\"", "").replace(" ", "")
    return hashlib.md5(current_str.encode("utf-8")).hexdigest()

    def get_authorization(sign: str, app_key: str) -> str:
    """
    @param sign: 签名
    @param app_key: 引力申请的开发者app_key
    """
    return jwt.encode({"app_key": app_key}, sign, algorithm="HS256")
    ```
  </Tab>
</Tabs>
