AWS API网关签名

我正在尝试向亚马逊网关签署我的请求。 但每当我尝试发送POST请求时,它都会告诉我我的签名已过期。 任何想法将不胜感激。

你有时间或类似的问题。 我遇到了有效载荷的问题。 因此,如果您正在进行GET请求,则您的有效负载是EMPTY STRING 。 否则应该散列Json对象。 以下是我在应用程序中如何执行此操作的示例。 代码可以是原始的,但我有100000%的工作,因为我每天都在使用它。

const string RegionName = "eu-west-1"; //This is the regionName const string ServiceName = "apigateway"; const string Algorithm = "AWS4-HMAC-SHA256"; const string ContentType = "application/json"; const string Host = "apigateway.eu-west-1.amazonaws.com"; const string SignedHeaders = "content-type;host;x-amz-date"; public static WebRequest RequestGet(string canonicalUri, string canonicalQueriString, string jsonString) { string hashedRequestPayload = CreateRequestPayload(""); string authorization = Sign(hashedRequestPayload, "GET", canonicalUri, canonicalQueriString); string requestDate = DateTime.UtcNow.ToString("yyyyMMddTHHmmss") + "Z"; WebRequest webRequest = WebRequest.Create("https://" + Host + canonicalUri); webRequest.Method = "GET"; webRequest.ContentType = ContentType; webRequest.Headers.Add("X-Amz-date", requestDate); webRequest.Headers.Add("Authorization", authorization); webRequest.Headers.Add("x-amz-content-sha256", hashedRequestPayload); return webRequest; } public static WebRequest RequestPost(string canonicalUri, string canonicalQueriString, string jsonString) { string hashedRequestPayload = CreateRequestPayload(jsonString); string authorization = Sign(hashedRequestPayload, "POST", canonicalUri, canonicalQueriString); string requestDate = DateTime.UtcNow.ToString("yyyyMMddTHHmmss") + "Z"; WebRequest webRequest = WebRequest.Create("https://" + Host + canonicalUri); webRequest.Timeout = 20000; webRequest.Method = "POST"; webRequest.ContentType = ContentType; webRequest.Headers.Add("X-Amz-date", requestDate); webRequest.Headers.Add("Authorization", authorization); webRequest.Headers.Add("x-amz-content-sha256", hashedRequestPayload); webRequest.ContentLength = jsonString.Length; ASCIIEncoding encoding = new ASCIIEncoding(); byte[] data = encoding.GetBytes(jsonString); Stream newStream = webRequest.GetRequestStream(); newStream.Write(data, 0, data.Length); return webRequest; } private static string CreateRequestPayload(string jsonString) { //Here should be JSON object of the model we are sending with POST request //var jsonToSerialize = new { Data = String.Empty }; //We parse empty string to the serializer if we are makeing GET request //string requestPayload = new JavaScriptSerializer().Serialize(jsonToSerialize); string hashedRequestPayload = HexEncode(Hash(ToBytes(jsonString))); return hashedRequestPayload; } private static string Sign(string hashedRequestPayload, string requestMethod, string canonicalUri, string canonicalQueryString) { var currentDateTime = DateTime.UtcNow; var accessKey = //Here place your app ACCESS_KEY var secretKey = //Here is a place for you app SECRET_KEY var dateStamp = currentDateTime.ToString("yyyyMMdd"); var requestDate = currentDateTime.ToString("yyyyMMddTHHmmss") + "Z"; var credentialScope = string.Format("{0}/{1}/{2}/aws4_request", dateStamp, RegionName, ServiceName); var headers = new SortedDictionary < string, string > { { "content-type", ContentType }, { "host", Host }, { "x-amz-date", requestDate } }; string canonicalHeaders = string.Join("\n", headers.Select(x => x.Key.ToLowerInvariant() + ":" + x.Value.Trim())) + "\n"; // Task 1: Create a Canonical Request For Signature Version 4 string canonicalRequest = requestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + SignedHeaders + "\n" + hashedRequestPayload; string hashedCanonicalRequest = HexEncode(Hash(ToBytes(canonicalRequest))); // Task 2: Create a String to Sign for Signature Version 4 string stringToSign = Algorithm + "\n" + requestDate + "\n" + credentialScope + "\n" + hashedCanonicalRequest; // Task 3: Calculate the AWS Signature Version 4 byte[] signingKey = GetSignatureKey(secretKey, dateStamp, RegionName, ServiceName); string signature = HexEncode(HmacSha256(stringToSign, signingKey)); // Task 4: Prepare a signed request // Authorization: algorithm Credential=access key ID/credential scope, SignedHeadaers=SignedHeaders, Signature=signature string authorization = string.Format("{0} Credential={1}/{2}/{3}/{4}/aws4_request, SignedHeaders={5}, Signature={6}", Algorithm, accessKey, dateStamp, RegionName, ServiceName, SignedHeaders, signature); return authorization; } private static byte[] GetSignatureKey(string key, string dateStamp, string regionName, string serviceName) { byte[] kDate = HmacSha256(dateStamp, ToBytes("AWS4" + key)); byte[] kRegion = HmacSha256(regionName, kDate); byte[] kService = HmacSha256(serviceName, kRegion); return HmacSha256("aws4_request", kService); } private static byte[] ToBytes(string str) { return Encoding.UTF8.GetBytes(str.ToCharArray()); } private static string HexEncode(byte[] bytes) { return BitConverter.ToString(bytes).Replace("-", string.Empty).ToLowerInvariant(); } private static byte[] Hash(byte[] bytes) { return SHA256.Create().ComputeHash(bytes); } private static byte[] HmacSha256(string data, byte[] key) { return new HMACSHA256(key).ComputeHash(ToBytes(data)); } 

因此,例如,如果我想获得在Gateway中部署的所有API,我这样做:

 using(WebResponse response = webRequest.GetResponse()) { StreamReader responseReader = new StreamReader(response.GetResponseStream()); string responseJson = responseReader.ReadToEnd(); } catch (WebException) { //Doing something when exception has been thrown } 

以下是创建API密钥的有趣部分。 首先,您需要制作原始有效负载,然后将其传递给我上面给出的方法:

 string payload = "{ \"name\" : \"" + name + "\", \"description\" : \"" + description.Trim() + "\", \"enabled\" : \"True\", \"stageKeys\" : [ ] }"; WebRequest webRequest = RequestSignerAWS.RequestPost("/apikeys", "", payload); 

并确保您获得创建请求的时间,因为这将导致您遇到的问题。