问题描述
我正在尝试创建一个 SAS Token
以使用 JavaScript (Express.js) 与 Azure API Management Rest API 进行通信。但使用它实际上让我想到了 401 Unauthorized
。我正在使用以下代码行。
// setting one day expiry time
const expiryDate = new Date(Date.Now() + 1000 * 60 * 60 * 24)
const expiryString = expiryDate.toISOString()
const identifier = process.env.AZURE_APIM_IDENTIFIER
const key = process.env.AZURE_APIM_SECRET_KEY ?? ""
const stringToSign = `${identifier}\n${expiryString}`
const signature = CryptoJS.HmacSHA256(stringToSign,key)
const encodedSignature = CryptoJS.enc.Base64.stringify(signature)
// SAS Token
const sasToken = `SharedAccessSignature uid=${identifier}&ex=${expiryString}&sn=${encodedSignature}`
上面的代码片段返回给我的是这样的:
SharedAccessSignature uid=integration&ex=2021-04-21T10:48:04.402Z&sn=**O8KZAh9zVHw6Dmb03t1xlhTnrmP1B6i+5lbhQWe**=
(为了安全起见隐藏了一些字符,但字符数是真实的)
请注意,上述 SAS 令牌中只有一个尾随 破折号 =
,而所有示例中的 SAS 令牌和从 API 管理门户手动创建的 SAS 令牌都有 2 个破折号 ==
我做错了什么吗?
提前致谢。
解决方法
根据Azure APIM SAS token的document,我们可以看到示例是c#代码:
示例与您的代码之间的区别在于,c# 示例使用 HMACSHA512,而您的代码使用 HMAS256。所以我认为你还需要在你的 nodejs 中使用 HMACSHA512。你可以这样做:
var hash = crypto.createHmac('sha512',key);
您可能还需要执行 hash.update(text);
和 hash.digest()
,请参阅此 document。
谢谢Hury Shen!我还发现我们不需要 crypto-js
for(因为我们必须为此导入一个外部库)。 Node 有 crypto
作为它的原生模块,我们可以使用它。以下 JavaScript 代码段工作正常。
import crypto from "crypto"
const identifier = <YOUR_AZURE_APIM_IDENTIFIER>
const secretKey = <YOUR_AZURE_APIM_SECRET_KEY>
// setting token expiry time
const expiryDate = new Date(Date.now() + 1000 * 60 * 60 * 24 * 29)
const expiryString = expiryDate.toISOString().slice(0,-1) + "0000Z"
const dataToSign = `${identifier}\n${expiryString}`
// create signature
const signedData = crypto
.createHmac("sha512",secretKey)
.update(dataToSign)
.digest("base64")
// SAS Token
const accessToken = `SharedAccessSignature uid=${identifier}&ex=${expiryString}&sn=${signedData}`