I'm using the Amazon S3 environment to store images for a C# Webapplication. From the S3 documentation I learned, that the basic URL to access an object looks like
http://[bucket-name].S3.amazonaws.com/[key]
I know that one can build expiring URLs to the objects in a bucket. Two questions:
Amazon S3 supports both virtual-hosted–style and path-style URLs to access a bucket. Because buckets can be accessed using path-style and virtual-hosted–style URLs, we recommend that you create buckets with DNS-compliant bucket names. For more information, see Bucket restrictions and limitations.
You can only test the endpoint for your domain bucket because your subdomain bucket is set up for website redirect and not static website hosting. Amazon S3 does not support HTTPS access to the website. If you want to use HTTPS, you can use Amazon CloudFront to serve a static website hosted on Amazon S3.
To generate a presigned URL using the AWS Management ConsoleSign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/ . In the Buckets list, choose the name of the bucket that contains the object that you want a presigned URL for.
An S3 bucket can be accessed through its URL. The URL format of a bucket is either of two options: http://s3.amazonaws.com/[bucket_name]/ http://[bucket_name].s3.amazonaws.com/
You only need to build expiring urls if you want to restrict access.
Here's some code to generate the signed url which expires in 3 mins.
using (var s3Client = AWSClientFactory.CreateAmazonS3Client("MyAccessKey", "MySecretKey"))
{
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
.WithBucketName("MyBucketName")
.WithKey("MyFileKey")
.WithProtocol(Protocol.HTTP)
.WithExpires(DateTime.Now.AddMinutes(3));
string url = s3Client.GetPreSignedURL(request);
}
This is code from S3SignURL, It uses no outside DLL's just pure core C#
https://github.com/DigitalBodyGuard/S3SignURL/
using System;
using System.Collections.Generic;
using System.Text;
namespace s3_polocySigning
{
public static class Encode
{
// static string thanks = "http://stackoverflow.com/questions/6999648/signing-post-form-in-c-sharp-for-uploading-to-amazon-s3";
public static string BuildURL(string AccessKey, string SecretKey, DateTime timeToExpire, string BucketName, string FileKey)
{
System.Security.Cryptography.HMAC hmacProvider = System.Security.Cryptography.HMAC.Create();
string returnString = string.Empty;
hmacProvider.Key = System.Text.ASCIIEncoding.ASCII.GetBytes(SecretKey);
string expirationString = ConvertToUnixTimestamp(timeToExpire).ToString();
//System.Uri.UriSchemeHttp &/ System.Web.HttpUtility.UrlEncode
string assembledRequest = "GET" + "\n" + "\n" + "\n" + expirationString + "\n" + "/" + BucketName + "/" + UrlEncode(FileKey);
byte[] hashedSignature = hmacProvider.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(assembledRequest));
returnString = Convert.ToBase64String(hashedSignature);
return "https://" + "s3.amazonaws.com/" + BucketName + "/" + FileKey + "?AWSAccessKeyId=" + AccessKey + "&Expires=" + expirationString + "&Signature=" + UrlEncode(returnString);
}
private static double ConvertToUnixTimestamp(DateTime ExpDate)
{
if (DateTime.MinValue == ExpDate)
return 2133721337;
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
TimeSpan diff = ExpDate - origin;
return Convert.ToDouble(Math.Floor(diff.TotalSeconds));
}
public static string GetSig(string policyStr, string secretKey)
{
policyStr = GetBase64_string(policyStr);
var signature = new System.Security.Cryptography.HMACSHA1(GetBase64(secretKey));
var bytes = GetBase64(policyStr);
var moreBytes = signature.ComputeHash(bytes);
var encodedCanonical = Convert.ToBase64String(moreBytes);
return encodedCanonical;
}
public static string GetBase64_string(string policyStr)
{
policyStr = policyStr.Replace("/r", "").Replace("/n", "").Replace(System.Environment.NewLine, "\n");
return Convert.ToBase64String(Encoding.ASCII.GetBytes(policyStr));
}
public static byte[] GetBase64(string policyStr)
{
return Encoding.ASCII.GetBytes(policyStr);
}
// ThanksTo = "http://www.west-wind.com/weblog/posts/2009/Feb/05/Html-and-Uri-String-Encoding-without-SystemWeb";
// avoid useing System.Web.HttpUtility.UrlEncode
/// <summary>
/// UrlEncodes a string without the requirement for System.Web
/// </summary>
/// <param name="String"></param>
/// <returns></returns>
// [Obsolete("Use System.Uri.EscapeDataString instead")]
public static string UrlEncode(string text)
{
// Sytem.Uri provides reliable parsing
return System.Uri.EscapeDataString(text);
}
/// <summary>
/// UrlDecodes a string without requiring System.Web
/// </summary>
/// <param name="text">String to decode.</param>
/// <returns>decoded string</returns>
public static string UrlDecode(string text)
{
// pre-process for + sign space formatting since System.Uri doesn't handle it
// plus literals are encoded as %2b normally so this should be safe
text = text.Replace("+", " ");
return System.Uri.UnescapeDataString(text);
}
/// <summary>
/// Retrieves a value by key from a UrlEncoded string.
/// </summary>
/// <param name="urlEncoded">UrlEncoded String</param>
/// <param name="key">Key to retrieve value for</param>
/// <returns>returns the value or "" if the key is not found or the value is blank</returns>
public static string GetUrlEncodedKey(string urlEncoded, string key)
{
urlEncoded = "&" + urlEncoded + "&";
int Index = urlEncoded.IndexOf("&" + key + "=", StringComparison.OrdinalIgnoreCase);
if (Index < 0)
return "";
int lnStart = Index + 2 + key.Length;
int Index2 = urlEncoded.IndexOf("&", lnStart);
if (Index2 < 0)
return "";
return UrlDecode(urlEncoded.Substring(lnStart, Index2 - lnStart));
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With