我已经为这个问题苦苦挣扎了3天。我真的很感谢您的帮助。
我正在尝试创建SAS令牌以动态访问Azure存储Blob,该令牌会生成,但是我一直收到此错误:
Signature did not match. String to sign used was ...
从azure门户创建SAS令牌工作正常,但是我尝试使用多种方法在代码中生成它,即Micrtosoft.Azure.Storage库:
private static string GetBlobSasUri(CloudBlobContainer container, string blobName)
{
string sasBlobToken;
// Get a reference to a blob within the container.
// Note that the blob may not exist yet, but a SAS can still be created for it.
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
// Create a new access policy and define its constraints.
// Note that the SharedAccessBlobPolicy class is used both to define the parameters of an ad hoc SAS, and
// to construct a shared access policy that is saved to the container's shared access policies.
SharedAccessBlobPolicy adHocSAS = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed to be the time when the storage service receives the request.
// Omitting the start time for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessStartTime = DateTime.UtcNow.AddHours(-24),
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Read //| SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Create
};
// Generate the shared access signature on the blob, setting the constraints directly on the signature.
sasBlobToken = blob.GetSharedAccessSignature(adHocSAS);
Console.WriteLine("SAS for blob (ad hoc): {0}", sasBlobToken);
Console.WriteLine();
// Return the URI string for the container, including the SAS token.
return blob.Uri + sasBlobToken;
}
这已经尝试了好几次,第二天停止运行。.我在本地IIS和Azure上对其进行了测试,在本地却从未起作用。
我也尝试过自己创建令牌,生成令牌并对其进行签名,但是仍然存在相同的问题..这是签名的代码:
public static string generateSAS(Uri resourceUri, string accountKey, string accountName, StorageFile f)
{
string
sr = "b",
sp = "r",
st = DateTime.Now.AddHours(-50).ToString("yyyy-MM-ddTH:MM:ssZ"),
se = DateTime.Now.AddHours(50).ToString("yyyy-MM-ddTH:MM:ssZ"),
sv = "2016-05-31"; //"2019-07-07"
string blobUri = $"https://{accountName}.blob.core.windows.net/{f.Model.Container}/{f.Model.FileName}";
string stringToSign = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n{9}\n{10}\n{11}\n{12}", new object[]
{
"r",
st,
se,
GetCanonicalizedResource(new Uri(blobUri), accountName),
string.Empty,
string.Empty,
string.Empty,
sv,
sr,
string.Empty,
string.Empty,
string.Empty,
string.Empty
});
var sas = GetHash(stringToSign, accountKey);
var token =
$"?sv={sv}&sr=b&sig={HttpUtility.UrlEncode(sas)}&st={HttpUtility.UrlEncode(st)}&se={HttpUtility.UrlEncode(se)}&sp=r";
return blobUri + token;
}
private static string GetHash(string stringToSign, string key)
{
byte[] keyValue = Convert.FromBase64String(key);
using (HMACSHA256 hmac = new HMACSHA256(keyValue))
{
return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
}
}
private static string GetCanonicalizedResource(Uri address, string storageAccountName)
{
// The absolute path is "/" because for we're getting a list of containers.
StringBuilder sb = new StringBuilder("/").Append("blob").Append("/").Append(storageAccountName).Append(address.AbsolutePath);
return sb.ToString();
}
我已经阅读了文档,并认为该问题可能是版本问题,因此我尝试使用最新版本和之前的某些版本,但无济于事。
我尝试不使用和添加其他参数,根本没有任何效果。
我也被认为是时钟问题,但是到目前为止,我已经将时钟调整为每天的每个小时,并且已经在Azure上的应用服务上进行了测试,该服务位于“ UK South”,在那里的C#代码用了不到一天的时间。
非常感谢您的帮助!谢谢
编辑 使用我手动对其进行自我签名的RESTful版本代码,即“ toSignString”:
r
2020-02-17T14:02:56Z
2020-02-21T18:02:56Z
/blob/<accountName>/<contaioner1>/<subContainer2>/<subContainer3>/file.v
2016-05-31
b
这是完整的Uri:
https://<account>.blob.core.windows.net/<contaioner1>/<subContainer2>/<subContainer3>/file.v?
sv=2016-05-31&sr=b&sig=hI7MH0pT05cDpga2bMkanR%2b77CeocgttygDJbkRw6EM%3d&st=2020-02-17T14%3a02%3a56Z&se=2020-02-21T18%3a02%3a56Z&sp=r
答案 0 :(得分:1)
这已经工作了一天,然后停止工作了。我测试了 它在我的本地IIS和azure上都无法正常工作。
这是预期的行为,因为您将SAS令牌到期设置为距当前日期/时间24小时(以UTC为单位):
mix.js('resources/js/app.js', 'public/js')
.sass(commonSassFile, cssPublicDir+'/app_blue.css', {
data: '$theme-bg-primary: #1450d9;'
})
.sass(commonSassFile, cssPublicDir+'/app_red.css', {
data: '$theme-bg-primary: #ba0000;'
});
如果希望SAS URL更长的工作时间,则需要指定将来的有效期。
关于第二个问题(手动创建SAS令牌),我认为您的SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
方法存在问题。根据{{3}},它应采用以下格式:
GetCanonicalizedResource
字符串的canonicalizedresource部分是通向的规范路径 签名的资源。它必须包含服务名称(blob,表, 队列或文件)(版本为2015-02-21或更高版本),存储帐户 名称和资源名称,并且必须经过URL解码。
基于此,请尝试以下代码:
/blob/<account-name>/<container-name>/<blob-name>
让我花点时间找出问题所在:),但终于可以了。我发现了许多问题:
private static string GetCanonicalizedResource(Uri address, string storageAccountName)
{
// The absolute path is "/" because for we're getting a list of containers.
StringBuilder sb = new StringBuilder("/").Append("blob").Append("/").Append(storageAccountName).Append("/").Append(address.AbsolutePath);
return sb.ToString();
}
,但您要以yyyy-MM-ddTHH:MM:ssZ
格式对其进行格式化。如果您注意到,它会丢失额外的yyyy-MM-ddTH:MM:ssZ
。H
签名版本,但2016-05-31
中不包括签名资源(在您的情况下为b
),但您要包括该签名资源。但是,它应该包含在您的SAS URL中。stringToSign
参数。根据文档,这就是构造content-language (rscl)
的方式:
stringToSign
基于此,这应该是您的代码:
StringToSign = signedpermissions + "\n" +
signedstart + "\n" +
signedexpiry + "\n" +
canonicalizedresource + "\n" +
signedidentifier + "\n" +
signedIP + "\n" +
signedProtocol + "\n" +
signedversion + "\n" +
rscc + "\n" +
rscd + "\n" +
rsce + "\n" +
rscl + "\n" +
rsct
尝试一下,它应该可以工作。