我正在尝试通过Web服务为我的blob提供“只读”访问权限。 Web Service有一个方法,它接收Blob和Container信息,然后返回一个带有共享访问签名的URL,用户可以使用该URL访问blob。由于这些图像(blob)缓存在手机上,我希望签名有效期最长为1天。
我使用以下代码:
var blobClient = GetBlobClient();
var container = blobClient.GetContainerReference(containerName);
if (container != null)
{
container.CreateIfNotExist();
}
var policy = new SharedAccessPolicy()
{
SharedAccessStartTime = DateTime.Now,
Permissions = SharedAccessPermissions.Read,
SharedAccessExpiryTime = DateTime.Now.AddDays(days)
};
if (permissions.Contains("w"))
{
policy.Permissions = policy.Permissions | SharedAccessPermissions.Write;
policy.SharedAccessExpiryTime = DateTime.Now.AddMinutes(10);
}
//The shared access policy provides read/write access to the container for 10 hours.
BlobContainerPermissions containerPerms = new BlobContainerPermissions();
// The public access setting explicitly specifies that the container is private,
// so that it can't be accessed anonymously.
containerPerms.PublicAccess = BlobContainerPublicAccessType.Off;
containerPerms.SharedAccessPolicies.Clear();
containerPerms.SharedAccessPolicies.Add("mypolicy", policy);
// Set the permission policy on the container.
container.SetPermissions(containerPerms);
var blob = container.GetBlobReference(blobName);
// Get the shared access signature to share with users.
var blobPolicy = new SharedAccessPolicy();
blobPolicy.SharedAccessExpiryTime = DateTime.Now.AddDays(days);
blobPolicy.Permissions = SharedAccessPermissions.Read;
string sas = blob.GetSharedAccessSignature(blobPolicy, "mypolicy");
return sas;
每次我尝试使用此代码时,都会收到以下错误: 签名不匹配。要使用的字符串是r 2012-01-03T08:38:52Z /myContainer/12100/12409/29cae1b6-2955-4a33-ab27-ff99f0bb6470_m.jpg mypolicy
有人可以指导我吗?
答案 0 :(得分:3)
我怀疑问题在于您网址的“签名”组件(sig参数)。
如果您使用的是没有政策的60分钟网址,则访问您的BLOB的网址必须采用此格式:
http://[storage account name].blob.core.windows.net/[top level container name]/[filename of BLOB]?sr=b&st=2012-01-19T12:21:40Z&se=2012-01-19T13:21:40Z&sp=r&sig=[Base-64 encoded signature]
如果您使用的是政策,请使用此格式:
http://[storage account name].blob.core.windows.net/[top level container name]/[filename of BLOB]?sr=b&st=2012-01-19T12:21:40Z&se=2012-01-19T13:21:40Z&si=[name of security policy]&sig=[Base-64 encoded signature]
关于签名(URL上的sig参数:) Microsoft伪代码显示了他们希望我们如何生成签名:
Signature=Base64(HMAC-SHA256(UTF8(StringToSign)))
你如何制作字符串到符号?见http://msdn.microsoft.com/en-us/library/windowsazure/ee395415.aspx
StringToSign = signedpermissions +“\ n” + signedstart +“\ n” + signedexpiry +“\ n” + canonicalizedresource +“\ n” + signedidentifier
换行是至关重要的 - 这些等同于十六进制字符0xA。标准Java“\ n”换行没问题。不要将它们遗漏或不起作用。
对于signedpermissions,可以为null - 只要在signedpermissions之后仍然包含换行符,如果它为null。
如果填充了signedpermissions,那么signedidentifier就可以为null。您不需要在其后面添加换行符。
在对其运行HMAC SHA256哈希之前,必须确保将字符串转换为UTF-8(Unicode 8)。
请参阅http://msdn.microsoft.com/en-us/library/windowsazure/hh508996.aspx
字符串到符号是一个唯一的字符串,由必须验证的字段构成,以便对请求进行身份验证。签名是使用SHA256算法通过字符串到符号和密钥计算的HMAC,然后使用Base64编码进行编码。
答案 1 :(得分:1)
看起来您正在为容器上的“mypolicy”完全设置SAS策略。一旦这样做,它们就不会对查询字符串参数的后续修改开放。这是一个“填空”系统。您可以在查询字符串上指定的唯一部分是尚未指定并保存在容器策略中的部分(即填充空白)。所以,在这种情况下,你有
blobPolicy.SharedAccessExpiryTime = DateTime.Now.AddDays(days);
blobPolicy.Permissions = SharedAccessPermissions.Read;
但是,这两个选项已经保存在策略中,因此您无法再次指定它们(它们会添加到生成的查询字符串中)。如果要指定它们,则不应将它们保存在初始SetPermission()上。
您可以通过注释掉这两行来证明这一点,并且您的结果签名应该有效。
答案 2 :(得分:0)
这可能是因为共享访问签名不能超过一小时。为了拥有一个多小时的SAS,您需要使用容器级策略(可以撤销) 摘录自article
您可以管理共享访问签名的一种方法是进行控制 它的生命周期通过确保它在一小时内到期。如果你想 在此之后继续授予客户端访问blob的权限 期间,您必须签发新签名。这是一个行为 与容器级别无关的共享访问签名 访问政策。共享访问签名未绑定到 容器级访问策略无法撤销。如果是开始时间 指定的,到期时间必须是60分钟或更短的时间 开始时间,或签名无效,无法使用。如果不 指定开始时间,签名仅在60年期间有效 到期时间之前的一小段时间。本政策旨在 在签名的情况下最小化存储帐户的风险 泄露。
管理共享访问签名的另一种方法是关联 具有容器级访问策略的签名。容器级 访问策略由URL上的signedidentifier字段表示。 容器级访问策略提供了额外的度量 控制一个或多个共享访问签名,包括 能够在需要时撤销签名。