简体中文
简体中文
English
联系我们
注册
登录
语言
简体中文
简体中文
English
联系我们
登录
注册
返回主站
layout空间导航

签名机制

更新时间:2021-11-25 03:33:02下载pdf

您在向云开发平台发送调用请求时,都需要提供签名(Sign)进行身份验证。文本介绍如何构建云开发平台 API 签名。

签名算法

涂鸦采用 HMAC-SHA256 方法创建摘要,详见下方说明。

说明:

  • 您可以通过 Postman 工具,自主校验云端 API 请求中 sign 的加密结果,校验方法查看 验证签名结果
  • 为提供更安全的服务,涂鸦将对签名算法进行升级。在2021年6月30号之后创建的新项目仅支持使用新算法验签。2021年6月30日前创建的项目仍可使用 旧版签名校验方案,但是基于信息安全考虑,建议升级为新的签名算法。

令牌管理 API 签名算法

  • 适用范围:获取令牌和刷新令牌 API。

  • 签名算法: sign = HMAC-SHA256(client_id + t + nonce + stringToSign, secret).toUpperCase()

  • 算法逻辑:

    1. nonce为 API 调用者生成的UUID,结合时间戳防重复,nonce为非必填字段; stringToSign为签名字符串。
    2. 将 client_id 与当前请求的 13 位标准时间戳(t)、nonce、stringToSign 拼接成字符串。
    3. 将字符串和 secret 进行哈希摘要,得到新的字符串。
    4. 将新的字符串转为大写。

业务管理 API 签名算法

  • 适用范围:令牌管理接口以外的其他 API。

  • 签名算法:

    str = client_id + access_token + t + nonce + stringToSign
    sign = HMAC-SHA256(str, secret).toUpperCase()

  • 算法逻辑:

    1. nonce为 API 调用者生成的UUID,结合时间戳防重复,nonce为非必填字段; stringToSign为签名字符串。

    2. 将 client_id 、access_token 、当前请求的 13 位标准时间戳(t)、nonce、stringToSign 拼接成字符串。

    3. 将字符串和 secret 进行哈希摘要,得到新的字符串。

    4. 将新的字符串转为大写。

stringToSign签名字符串

  • 组成部分:

    String stringToSign= 
    HTTPMethod + "\n" + 
    Content-SHA256 + "\n" +
    Headers + "\n" +
    Url
    
  • 签名字符串字段:

    1. HTTPMethod:为全大写,如POST,PUT等。

    2. Content-SHA256: 是指Body的SHA256值,只有当Body非Form表单时才计算 SHA256,计算方式如下:

      String content-SHA256 = SHA256(bodyStream.getbytes("UTF-8")); //bodyStream为字节数组
      

      注意: 当body为空时,也会进行加密,加密结果为 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

    3. Headers:

      Headers是指参与签名计算的Header的Key、Value拼接的字符串。

      开发者将需要参与签名的Header的key拼接到一起,用英文冒号分隔,作为Signature-Headers的值。

      示例Header:

      client_id:xxx
      Signature-Headers : Key1:Key2
      Key1:xxx
      Key2:xxx
      key3:xxx (不会加到签名计算中)
      nonce:xxx
      ·····
      

      计算Headers(只计算出现在Signature-Headers里面的Key):

      String Headers =
      HeaderKey1 + ":" + HeaderValue1 + "\n" +
      HeaderKey2 + ":" + HeaderValue2 + "\n" +
      ...
      HeaderKeyN + ":" + HeaderValueN + "\n"
      
      
      
    4. URL: URL 指 Path+Query+Body 中 Form 参数,组织方法如下:

      对 Query+Form 参数按照字典对 Key 进行排序后,按照如下方法拼接,如果 Query 或 Form 参数为空,则URL=Path,不需要添加?

      String url =
      Path +
      "?" +
      Key1 + "=" + Value1 +
      "&" + Key2 + "=" + Value2 +
      "&" + Key3 + 
      ...
      "&" + KeyN + "=" + ValueN 
      

签名构建示例

示例参数

获取用户列表API 为例,schema参数为apps,无 body 参数。

注意: 接口调用请求头(Request header) 参数,请参考请求结构

参数名 参数值
URL /v2.0/apps/schema/users
method GET
client_id 1KAD46OrT9HafiKdsXeg
secret 4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC
t 1588925778000
access_token 3f4eda2bdec17232f67c0b188af3eec1
sign_method HMAC-SHA256
说明:签名的摘要算法,请求头必须添加
nonce 5138cc3a9033d69856923fd07b491173
Signature-Headers area_id:call_id
area_id (开发者自定义) 29a33e8796834b1efa6
call_id (开发者自定义) 8afdb70ab2ed11eb85290242ac130003
page_no 1
page_size 50

令牌管理 API 签名

  1. 拼接stringToSign签名字符串。

    stringToSign=GET
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    area_id:29a33e8796834b1efa6
    call_id:8afdb70ab2ed11eb85290242ac130003
    	
    /v1.0/token?grant_type=1
    
  2. 拼接待签名字符串。

    1KAD46OrT9HafiKdsXeg15889257780005138cc3a9033d69856923fd07b491173GET
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    area_id:29a33e8796834b1efa6
    call_id:8afdb70ab2ed11eb85290242ac130003
    
    /v1.0/token?grant_type=1
    
  3. 通过哈希摘要获得新字符。

    • 哈希摘要:

      HMAC-SHA256(1KAD46OrT9HafiKdsXeg15889257780005138cc3a9033d69856923fd07b491173GET
      e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
      area_id:29a33e8796834b1efa6
      call_id:8afdb70ab2ed11eb85290242ac130003
      
      /v1.0/token?grant_type=1,4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC)
      
    • 新字符:
      9e48a3e93b302eeecc803c7241985d0a34eb944f40fb573c7b5c2a82158af13e

  4. 转换为大写。
    9E48A3E93B302EEECC803C7241985D0A34EB944F40FB573C7B5C2A82158AF13E

业务管理 API 签名

  1. 拼接stringToSign签名字符串。

    stringToSign=GET
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    area_id:29a33e8796834b1efa6
    call_id:8afdb70ab2ed11eb85290242ac130003
    	
    /v2.0/apps/schema/users?page_no=1&page_size=50
    
  2. 拼接待签名字符串。

    1KAD46OrT9HafiKdsXeg3f4eda2bdec17232f67c0b188af3eec115889257780005138cc3a9033d69856923fd07b491173GET
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
    area_id:29a33e8796834b1efa6
    call_id:8afdb70ab2ed11eb85290242ac130003
    
    /v2.0/apps/schema/users?page_no=1&page_size=50
    
  3. 通过哈希摘要获得新字符。

    • 哈希摘要:

      HMAC-SHA256(1KAD46OrT9HafiKdsXeg3f4eda2bdec17232f67c0b188af3eec115889257780005138cc3a9033d69856923fd07b491173GET
      e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
      area_id:29a33e8796834b1efa6
      call_id:8afdb70ab2ed11eb85290242ac130003
      
      /v2.0/apps/schema/users?page_no=1&page_size=50,4OHBOnWOqaEC1mWXOpVL3yV50s0qGSRC)
      
    • 新字符:
      ae4481c692aa80b25f3a7e12c3a5fd9bbf6251539dd78e565a1a72a508a88784

  4. 转换为大写。
    AE4481C692AA80B25F3A7E12C3A5FD9BBF6251539DD78E565A1A72A508A88784

HMAC SHA256 的实现

Java

点击下载 Java 代码示例

Go

点击下载 Go 代码示例

Node.js

点击下载 Node.js 代码示例

Javascript

/**
Run the code online with this jsfiddle. Dependent upon an open source js library calledhttp://code.google.com/p/crypto-js/.
**/

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/enc-base64.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/hmac-sha256.min.js"></script>

<script>
  var hash = CryptoJS.HmacSHA256("Message", "secret");
  var hashInBase64 = hash.toString().toUpperCase();
  document.write(hashInBase64);
</script>

PHP

/**
PHP has built in methods for hash_hmac (PHP 5) and base64_encode (PHP 4, PHP 5) resulting in no outside dependencies. Say what you want about PHP but they have the cleanest code for this example.
**/

$s = strtoupper(hash_hmac("sha256", "Message", 'secret'));
echo var_dump($s);

C#

using System;
using System.Security.Cryptography;

namespace Test
{
  public class MyHmac
  {
    public static string Encrypt(string message, string secret)
            {
                secret = secret ?? "";
                var encoding = new System.Text.UTF8Encoding();
                byte[] keyByte = encoding.GetBytes(secret);
                byte[] messageBytes = encoding.GetBytes(message);
                using (var hmacsha256 = new HMACSHA256(keyByte))
                {
                    byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                    StringBuilder builder = new StringBuilder();
                    for (int i = 0; i < hashmessage.Length; i++)
                    {
                        builder.Append(hashmessage[i].ToString("x2"));
                    }
                    return builder.ToString().ToUpper();
                }
            }
  }
}

FAQ

Q:如何验证加密后的签名是否正确?
A:本地开发的用户可用基于 Postman 预先查看加密后的签名结果,查询方法参见 验证签名结果