在C#中是否有示例说明如何使用带有AWS v4 signature的开始策略对所有对象进行预签名,以使客户从各自的文件夹结构中下载对象,而不是分别对每个文档进行签名。
文档说:
https://s3.amazonaws.com/examplebucket/test.txt
?X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=<your-access-key-id>/20130721/us-east-1/s3/aws4_request
&X-Amz-Date=20130721T201207Z
&X-Amz-Expires=86400
&X-Amz-SignedHeaders=host
&X-Amz-Signature=<signature-value>
但是我的签名不适用于GET(下载)对象,正常工作可进行上传
void Main()
{
string bucket = "bucket-name-here";
string s3Key = "s3-key-here";
string s3Secret = "secret-here";
string s3Region = "us-east-1";
string Date = DateTime.UtcNow.ToString("yyyyMMdd");
string xAmzDate = DateTime.UtcNow.ToString("yyyyMMdd") + "T000000Z";
string expiration = DateTime.UtcNow.AddDays(1).ToString("yyyy-MM-ddTHH:mm:ssK");
string policyString = $@"{{""expiration"":""{expiration}"",""conditions"":[{{""bucket"":""{bucket}""}},{{""acl"":""private""}},[""starts-with"",""$key"",""Client_1""],[""starts-with"",""$Content-Type"",""""],[""starts-with"",""$filename"",""""],{{""x-amz-date"":""{xAmzDate}""}},{{""x-amz-credential"":""{s3Key}/{Date}/us-east-1/s3/aws4_request""}},{{""x-amz-algorithm"":""AWS4-HMAC-SHA256""}}]}}";
var policyStringBytes = Encoding.UTF8.GetBytes(policyString);
var policy = Convert.ToBase64String(policyStringBytes);
//policy.Dump();
byte[] signingKey = GetSigningKey(s3Secret, Date, s3Region, "s3");
byte[] signature = HmacSHA256(policy, signingKey);
var sign = ToHexString(signature);
sign.Dump();
}
static byte[] HmacSHA256(String data, byte[] key)
{
String algorithm = "HmacSHA256";
KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
kha.Key = key;
return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
}
private byte[] GetSigningKey(String key, String dateStamp, String regionName, String serviceName)
{
byte[] kSecret = Encoding.UTF8.GetBytes(("AWS4" + key).ToCharArray());
byte[] kDate = HmacSHA256(dateStamp, kSecret);
byte[] kRegion = HmacSHA256(regionName, kDate);
byte[] kService = HmacSHA256(serviceName, kRegion);
byte[] kSigning = HmacSHA256("aws4_request", kService);
return kSigning;
}
public static string ToHexString(byte[] data)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sb.Append(data[i].ToString("x2", CultureInfo.InvariantCulture));
}
return sb.ToString();
}
有关该问题的更多信息:在S3上,数百个客户端的数千个文档位于各自的文件夹结构中,如下所示。现在,每当客户希望下载其对象时,它们都会被我们的API签名以创建可下载的链接>,因此每个文档都分别进行了签名。
客户端1
Client_1/Document1.xyz
Client_1/Document2.xyz
客户端2
Client_2/Document1.xyz
Client_2/Document2.xyz
答案 0 :(得分:0)
用于S3 HTML表单POST
上传的签名算法允许您使用["starts-with","$key",...]
之类的约束对策略文档进行签名,但是S3的预签名URL不支持此功能。使用预先签名的URL,您不会签署策略文档,而是签署“规范请求”,该规范表示浏览器的 exact 请求。因此,不支持通配符或前缀。
我想到了两种选择。
CloudFront signed URLs and signed cookies确实在使用“自定义策略”(而不是“罐头策略”,更像S3支持的“罐头策略”)时支持策略文档,并且自定义策略允许*
URL,类似于["starts-with","$key",...]
,但使用浏览器将请求的URL。您只需执行一次签名,浏览器中运行的代码就可以重用该策略和签名。在CloudFront的背面,使用CloudFront签名的URL或签名的cookie在CloudFront的正面对请求进行身份验证之后,将CloudFront原始访问身份用于将请求实际发送到存储桶时对其进行签名。 (使用签名的Cookie,浏览器只会发出请求,并自动提交cookie,因此工作原理相同,但没有浏览器对URL的操纵。
或者,您的服务器可以调用安全令牌服务中的AssumeRole
操作,以生成一组供客户端使用的临时凭据,以对其自己的单独URL进行签名。
调用AssumeRole
时,您还可以传递可选的会话策略文档。如果这样做,则生成的临时凭据只能执行角色策略(“允许从存储桶读取”)和会话策略(“允许从存储桶读取以特定前缀开头的密钥”)所允许的操作。因此,获得的角色凭据只会允许用户访问其对象。