You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Service Bus访问令牌C#实现报格式错误求助

Azure Service Bus SAS令牌格式错误问题排查

问题描述

在Postman中使用JavaScript代码可正常生成Azure Service Bus的SharedAccessSignature访问令牌,但迁移至C#实现后,生成的令牌始终提示access token is malformed,即使令牌格式外观相似,仍怀疑编码环节存在遗漏。

可正常工作的JavaScript代码

const sharedKeyName = "RootManageSharedAccessKey"
const sharedKey = "xxx"
const uri = "https://d365-service-bus-dev.servicebus.windows.net/XX-XX/subscriptions/XXX/messages/head"

function createSharedAccessToken(uri, saName, saKey) { 
    if (!uri || !saName || !saKey) { 
            throw "Missing required parameter"; 
        } 
    var encoded = encodeURIComponent(uri); 
    var now = new Date(); 
    var week = 60*60*24*7;
    var ttl = Math.round(now.getTime() / 1000) + week;
    var signature = encoded + '\n' + ttl;
    const hash = CryptoJS.HmacSHA256(signature, saKey).toString(CryptoJS.enc.Base64)
    return 'SharedAccessSignature sr=' + encoded + '&sig=' +  
        encodeURIComponent(hash) + '&se=' + ttl + '&skn=' + saName; 
}

// Set broker properties e.g. sessionId
const brokerProperties = {
    'SessionId':'123'
}

// Set broker proerties variable
console.log() 
pm.variables.set("broker_properties", JSON.stringify(brokerProperties));
// Set access token variable
pm.variables.set('access_token', createSharedAccessToken(uri, sharedKeyName, sharedKey));

存在问题的C#代码

if (string.IsNullOrEmpty(uri) || string.IsNullOrEmpty(saName) || string.IsNullOrEmpty(saKey))
{
    throw new ArgumentException("Missing required parameter");
}

string encoded = Uri.EscapeDataString(uri);
DateTime now = DateTime.UtcNow;
int week = 60 * 60 * 24 * 7;
long ttl = (long)(now - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds + week;

string signature = encoded + "\n" + ttl;
byte[] keyBytes = Convert.FromBase64String(saKey);
using (var hmac = new HMACSHA256(keyBytes))
{
    byte[] signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(signature));
    string hash = Convert.ToBase64String(signatureBytes);
    Token ="SharedAccessSignature sr="+encoded+"&sig="+Uri.EscapeDataString(hash)+"&se="+ttl+"&skn="+saName;
}
Console.WriteLine(Token);

问题原因及修正方案

1. 参数分隔符错误

C#代码中使用了HTML实体&作为参数分隔符,但Azure Service Bus的SAS令牌要求使用普通的&分隔参数。JS代码中虽写了&,但Postman在处理变量时会自动转换为&,而C#直接生成&会导致服务端无法正确解析令牌结构,触发格式错误提示。

2. URI编码规则不一致

JavaScript的encodeURIComponent与C#的Uri.EscapeDataString对部分字符的编码逻辑不同:

  • JS的encodeURIComponent不会编码!、'、(、)、*这些字符
  • C#的Uri.EscapeDataString会编码这些字符

这会导致签名生成时的原始字符串不一致,最终生成的哈希值不匹配,令牌无效。

3. 时间戳计算差异

JS中使用Math.round对时间戳进行四舍五入,而C#中直接截断取整,可能导致过期时间差1秒(虽一般不会触发格式错误,但建议保持逻辑一致)。

修正后的C#代码

if (string.IsNullOrEmpty(uri) || string.IsNullOrEmpty(saName) || string.IsNullOrEmpty(saKey))
{
    throw new ArgumentException("Missing required parameter");
}

// 实现与JS encodeURIComponent等效的编码逻辑
string encoded = EncodeUriComponent(uri);
DateTime now = DateTime.UtcNow;
int week = 60 * 60 * 24 * 7;
// 时间戳四舍五入,与JS逻辑一致
long ttl = (long)Math.Round((now - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds) + week;

string signature = encoded + "\n" + ttl;
byte[] keyBytes = Convert.FromBase64String(saKey);
using (var hmac = new HMACSHA256(keyBytes))
{
    byte[] signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(signature));
    string hash = Convert.ToBase64String(signatureBytes);
    // 使用&作为参数分隔符,而非HTML实体
    Token = $"SharedAccessSignature sr={encoded}&sig={Uri.EscapeDataString(hash)}&se={ttl}&skn={saName}";
}
Console.WriteLine(Token);

// 等效于JS encodeURIComponent的方法
private static string EncodeUriComponent(string value)
{
    var result = new StringBuilder();
    foreach (char c in value)
    {
        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
            c == '-' || c == '_' || c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' || c == '(' || c == ')')
        {
            result.Append(c);
        }
        else
        {
            result.Append('%' + string.Format("{0:X2}", (int)c));
        }
    }
    return result.ToString();
}

内容的提问来源于stack exchange,提问作者hazim saleh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 10:22:02