go - 在 GoLang 中生成 CosmosDB 身份验证 token

标签 go azure-cosmosdb

我正在尝试按照此处的说明生成 CosmosDb 身份验证 token : https://learn.microsoft.com/en-us/rest/api/documentdb/access-control-on-documentdb-resources .

这是我在 GoLang 中的实现(我将所有参数替换为在上面文档的“示例编码”部分中找到的文字值):

import(
    "crypto/hmac"
    "crypto/sha256"
    "encoding/base64"
    "net/url")

func generateAuthToken(
    verb string,
    resourceType string,
    resourceId string,
    date string,
    base64Key string) string {

    // Example Key
    base64Key := "dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5JiwvW0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw=="
    msg := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n",
        "get",                            //verb
        "dbs",                            //resourceId
        "dbs/todolist",                   //resourceLink
        "thu, 27 apr 2017 00:51:12 gmt",  //RFC1123 date
        "")

    hasher := hmac.New(sha256.New, []byte(base64Key))
    hasher.Write([]byte(msg))
    signature := base64.StdEncoding.EncodeToString(hasher.Sum(nil))

    authHeader := fmt.Sprintf("type=master&ver=1.0&sig=%s", signature)
    return url.QueryEscape(authHeader)
}

我还从链接中获取了 C# 示例,并使用与引用相同的参数运行它。

这是我从 C# 实现(引用)中得到的:

"type%3Dmaster%26ver%3D1.0%26sig%3DSGWmGNFZlBH%2Bt9QCvuMy%2FVsbBAOKLbxsgy3Z7aG0PdA%3D"

这是我从我的 GoLang 实现中得到的:

"type%3Dmaster%26ver%3D1.0%26sig%3Dwst1NDxfOeoYMurn69DgZtJUQOrgxFz%2Bp6A2vKnXxEI%3D"

很明显,我在 GoLang 实现中做错了,因为两者并不相同(可能误用了哈希库?)

为了便于引用,这里是 C# 实现:

static void Main(string[] args) {
      string token = GenerateAuthToken(
             "get",
             "dbs",
             "dbs/todolist",
             "thu, 27 apri 2017 00:51:12 gmt", 
             "dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5JiwvW0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw==",
             "master",
             "1.0");
}

static string GenerateAuthToken(string verb, string resourceType, string resourceId, string date, string key, string keyType, string tokenVersion)
{
      var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };

      verb = verb ?? "";
      resourceType = resourceType ?? "";
      resourceId = resourceId ?? "";

      string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n",
            verb.ToLowerInvariant(),
            resourceType.ToLowerInvariant(),
            resourceId,
            date.ToLowerInvariant(),
            "");

      byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
      string signature = Convert.ToBase64String(hashPayLoad);

      return System.Net.WebUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}",
            keyType,
            tokenVersion,
            signature));
}

最佳答案

这比我希望的要花更长的时间才找到。有一个明显的问题,你没有对这一行的 key 进行 base64 解码

hasher := hmac.New(sha256.New, []byte(base64Key))

你应该做类似的事情

hmacKey, _ := base64.StdEncoding.DecodeString(base64Key)
// handle error
hasher := hmac.New(sha256.New, hmacKey)

但即便如此也没有解决问题。直到我终于弄清楚了这个差异

C# "thu, 27 apri 2017 00:51:12 gmt"
Go "thu, 27 apr 2017 00:51:12 gmt" 

这行得通

func generateAuthToken(
    verb string,
    resourceType string,
    resourceId string,
    date string,
    base64Key string) string {

    msg := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n",
        verb,
        resourceType,
        resourceId,
        date,
        "")

    hmacKey, _ := base64.StdEncoding.DecodeString(base64Key)
    // handle error
    hasher := hmac.New(sha256.New, hmacKey)
    hasher.Write([]byte(msg))
    signature := base64.StdEncoding.EncodeToString(hasher.Sum(nil))

    authHeader := fmt.Sprintf("type=master&ver=1.0&sig=%s", signature)
    return url.QueryEscape(authHeader)
}

这是一个 Go Playground Link

因此,Go 版本几乎正确( key 除外),C# 部分几乎正确(非 RFC1123 格式除外)。

关于go - 在 GoLang 中生成 CosmosDB 身份验证 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46625098/

相关文章:

Azure,DocumentDB无法将POCO对象保存为文档

sql - 使用 SQL 检查 CosmosDB JSON 中是否存在字段 - nodeJS

c# - 使用 Id 列表查询 CosmosDB 的建议方法是什么

javascript - 如何正确地将 WASM 集成到 Angular 服务中

Golang变量声明语法含义

go - channel 缓冲区比 Go 中的预期多取一个值

go - golang的websocket服务端如何主动向客户端发送消息

go - 此类型声明有什么作用?

azure - CosmosDb 意外的延续 token

azure - CosmosDB - 正确的分区键