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

Azure Notification Hub Java调用报无效授权令牌签名错误求助

解决Azure Notification Hub Java SDK的Invalid authorization token signature错误

看起来你的问题核心出在SAS令牌的生成逻辑上,和PHP版本的处理存在几个关键差异,导致签名验证失败。下面是具体的问题分析和修正建议:

关键问题点

1. 错误使用HTML实体分隔符&而非&

在构造最终的SAS令牌字符串时,你用了&作为参数分隔符——这是HTML中的转义字符,但SAS令牌的参数应该用普通的&分隔。服务器会把&sig当成一个完整的参数名,而非解析为sig参数,这直接导致签名无法被正确识别,是引发错误的主要原因。

2. 重复对URI进行小写转换

你对URI做了两次toLowerCase()处理:

targetUri = URLEncoder.encode(uri.toString().toLowerCase(), "UTF-8").toLowerCase();

这可能会导致和PHP版本的URI编码结果不一致(比如PHP中可能只对原始URI做一次编码,没有额外转小写),进而影响签名的原始字符串内容,破坏签名一致性。

3. 签名的URL编码逻辑与PHP不一致

Base64编码后的签名包含+、/、=这些需要URL转义的字符,PHP的常用实现会直接替换为URL安全的版本(比如-代替+,_代替/,去掉=),而你的Java代码用URLEncoder.encode会把+转成%2B,/转成%2F,这也会导致签名不匹配。

修正后的generateSasToken方法

下面是调整后的代码,修复了上述所有问题:

private String generateSasToken(URI uri) {
    try {
        // 只对原始URI进行一次URL编码,保留原始大小写(URI本身大小写不敏感,无需额外转小写)
        String targetUri = URLEncoder.encode(uri.toString(), "UTF-8");
        
        // 计算过期时间(Unix时间戳,单位秒)
        long expires = System.currentTimeMillis() / 1000 + SdkGlobalSettings.getAuthorizationTokenExpirationInMinutes() * 60;
        
        // 构造待签名的字符串
        String toSign = targetUri + "\n" + expires;
        
        // 使用HMAC-SHA256生成签名(和PHP使用的算法保持一致)
        byte[] keyBytes = SasKeyValue.getBytes("UTF-8");
        SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(toSign.getBytes("UTF-8"));
        
        // 生成URL安全的Base64签名,和PHP处理逻辑对齐
        String signature = Base64.encodeBase64String(rawHmac)
                .replace('+', '-')
                .replace('/', '_')
                .replaceAll("=", "");
        
        // 构造SAS令牌,使用&作为参数分隔符
        String token = String.format("SharedAccessSignature sr=%s&sig=%s&se=%d&skn=%s",
                targetUri,
                signature,
                expires,
                SasKeyName);
        
        System.out.println(token);
        return token;
    } catch (Exception e) {
        throw new RuntimeException("Failed to generate SAS token", e);
    }
}

额外验证点

  • 确保SasKeyValue是Azure Portal中复制的完整SharedAccessKey,没有多余的空格或换行符(既然PHP能运行,这个大概率没问题,但还是确认下)。
  • 确认SasKeyName和你使用的SharedAccessKeyName完全一致(比如你代码里的DefaultFullSharedAccessSignature)。
  • 检查Notification Hub的名称和Endpoint是否和PHP代码中使用的完全匹配。

这些调整应该能让Java版本的SAS令牌生成逻辑和PHP对齐,解决签名无效的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:23:41