C# AWS TranslateText REST API调用添加签名v4
实际上,这不是一个问题,而是那些试图在没有SDK的情况下使用AWS TranslateText的人的答案。我有很多问题,直到我得到一个运行版本 在我看来,此服务的AWS文档并不完整,并且没有太多的示例可供检查(至少对于.Net而言) 起初,我认为我没有生成正确的V4签名,但在再次检查步骤和值之后,我决定使用Postman调用该服务。这很有帮助 邮递员可以生成AWS签名!(是的,我不知道)所以最后我注意到签名值不是问题所在 通过检查请求,我可以看到所需的标题及其一些值 我的问题是我没有发送“x-amz-target”头。 碰巧我发现这个头的值必须是“AWSShineFrontendService_20170701.TranslateText” (我在这里看到了类似的值) 另一个链接也很有帮助 现在我有了一个运行版本,我想分享我的.Net代码。我希望它有帮助:)C# AWS TranslateText REST API调用添加签名v4,c#,rest,amazon-web-services,signature,translate,C#,Rest,Amazon Web Services,Signature,Translate,实际上,这不是一个问题,而是那些试图在没有SDK的情况下使用AWS TranslateText的人的答案。我有很多问题,直到我得到一个运行版本 在我看来,此服务的AWS文档并不完整,并且没有太多的示例可供检查(至少对于.Net而言) 起初,我认为我没有生成正确的V4签名,但在再次检查步骤和值之后,我决定使用Postman调用该服务。这很有帮助 邮递员可以生成AWS签名!(是的,我不知道)所以最后我注意到签名值不是问题所在 通过检查请求,我可以看到所需的标题及其一些值 我的问题是我没有发送“x-a
使用Newtonsoft.Json.Linq;
使用制度;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
Net系统;
使用System.Security.Cryptography;
使用系统文本;
使用System.Web.Script.Serialization;
名称空间AWS_TranslateTextTest
{
类AWS_TranslateText
{
//用你自己的价值观来代替它
const string AccessKey=“AKI\u ADD\u YOUR\u AccessKey”;
const string SecretKey=“添加您的SecretKey”;
静态void Main()
{
尝试
{
string text=“将此文本从英语翻译为德语。”;
字符串sourceLang=“en”;
字符串targetLang=“de”;
字符串responseText=TranslateText(text、sourceLang、targetLang);
JObject json=JObject.Parse(responseText);
string translatedText=“;//从json或responseText读取响应
if(json.ToString()包含(“TranslatedText”)){
//要访问“点”表示法中的属性,请使用动态对象
动态obj=json;
translatedText=obj.translatedText.Value;
WriteLine(“TranslatedText为:{0}”,TranslatedText);
}
否则{
Console.WriteLine(“响应中未找到TranslatedText.”);
抛出新异常(json.ToString());
}
}
捕获(WebException ex)
{
控制台写入线(例如消息);
如果(例如响应!=null){
foreach(ex.Response.Headers中的字符串头)
{
WriteLine(“{0}:{1}”,header,ex.Response.Headers[header]);
}
使用(var responseStream=ex.Response.GetResponseStream())
{
if(responseStream!=null)
{
使用(var streamReader=newstreamreader(responseStream))
{
Console.WriteLine(streamReader.ReadToEnd());
}
}
} }
}
捕获(例外情况除外)
{
控制台写入线(例如消息);
}
}
私有静态字符串TranslateText(字符串文本、字符串源语言、字符串目标语言)
{
var date=DateTime.UtcNow;
常量字符串算法=“AWS4-HMAC-SHA256”;
常量字符串regionName=“eu-west-1”;
常量字符串serviceName=“translate”;
const string method=“POST”;
常量字符串canonicalUri=“/”;
常量字符串canonicalQueryString=“”;
常量字符串x_amz_target_header=“AWSShineFrontendService_20170701.TranslateText”;
const string contentType=“应用程序/x-amz-json-1.1”;
常量字符串主机=serviceName+“+regionName+”.amazonaws.com”;
var obj=新
{
SourceLanguageCode=sourceLang,
TargetLanguageCode=targetLang,
文本=文本
};
var requestPayload=newJavaScriptSerializer().Serialize(obj);
var hashedRequestPayload=HexEncode(Hash(ToBytes(requestPayload));
var dateStamp=日期.ToString(“yyyyMMdd”);
var requestDate=date.ToString(“yyyyMMddTHHmmss”)+“Z”;
var credentialScope=string.Format(“{0}/{1}/{2}/aws4_请求”,日期戳,区域名称,服务名称);
var bytes=ToBytes(请求有效负载);
var headers=新的SortedDictionary
{
{“内容长度”,bytes.length.ToString()},
{“内容类型”,内容类型},
{“主机”,主机},
{“x-amz-date”,requestDate},
{“x-amz-target”,x_-amz_-target_头}
};
字符串规范标头=
string.Join(“\n”,headers.Select(x=>x.Key.ToLowerInvariant()+”:“+x.Value.Trim())+”\n”;
字符串签名头=
string.Join(“;”,headers.Select(x=>x.Key.ToLowerInvariant());
//任务1:为签名版本4创建规范请求
var canonicalRequest=method+'\n'+canonicalUri+'\n'+canonicalQueryString+
'\n'+canonicalHeaders+'\n'+signedHeaders+'\n'+hashedRequestPayload;
var hashedCanonicalRequest=HexEncode(Hash(ToBytes(canonicalRequest));
//任务2:为签名版本4创建要签名的字符串
//StringToSign=Algorit
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web.Script.Serialization;
namespace AWS_TranslateTextTest
{
class AWS_TranslateText
{
// Replace this with your own values
const string AccessKey = "AKI_ADD_YOUR_ACCESSKEY";
const string SecretKey = "ADD_YOUR_SECRETKEY";
static void Main()
{
try
{
string text = "Translate this text from English to German.";
string sourceLang = "en";
string targetLang = "de";
string responseText = TranslateText(text, sourceLang, targetLang);
JObject json = JObject.Parse(responseText);
string translatedText = ""; // to do read response from json or responseText
if (json.ToString().Contains("TranslatedText")){
//To access to the properties in "dot" notation use a dynamic object
dynamic obj = json;
translatedText = obj.TranslatedText.Value;
Console.WriteLine("TranslatedText is: {0}", translatedText);
}
else{
Console.WriteLine("TranslatedText not found in response.");
throw new Exception(json.ToString());
}
}
catch (WebException ex)
{
Console.WriteLine(ex.Message);
if (ex.Response != null){
foreach (string header in ex.Response.Headers)
{
Console.WriteLine("{0}: {1}", header, ex.Response.Headers[header]);
}
using (var responseStream = ex.Response.GetResponseStream())
{
if (responseStream != null)
{
using (var streamReader = new StreamReader(responseStream))
{
Console.WriteLine(streamReader.ReadToEnd());
}
}
} }
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static string TranslateText(string text, string sourceLang, string targetLang)
{
var date = DateTime.UtcNow;
const string algorithm = "AWS4-HMAC-SHA256";
const string regionName = "eu-west-1";
const string serviceName = "translate";
const string method = "POST";
const string canonicalUri = "/";
const string canonicalQueryString = "";
const string x_amz_target_header = "AWSShineFrontendService_20170701.TranslateText";
const string contentType = "application/x-amz-json-1.1";
const string host = serviceName + "." + regionName + ".amazonaws.com";
var obj = new
{
SourceLanguageCode = sourceLang,
TargetLanguageCode = targetLang,
Text = text
};
var requestPayload = new JavaScriptSerializer().Serialize(obj);
var hashedRequestPayload = HexEncode(Hash(ToBytes(requestPayload)));
var dateStamp = date.ToString("yyyyMMdd");
var requestDate = date.ToString("yyyyMMddTHHmmss") + "Z";
var credentialScope = string.Format("{0}/{1}/{2}/aws4_request", dateStamp, regionName, serviceName);
var bytes = ToBytes(requestPayload);
var headers = new SortedDictionary<string, string>
{
{"content-length", bytes.Length.ToString()},
{"content-type", contentType},
{"host", host},
{"x-amz-date", requestDate},
{"x-amz-target", x_amz_target_header}
};
string canonicalHeaders =
string.Join("\n", headers.Select(x => x.Key.ToLowerInvariant() + ":" + x.Value.Trim())) + "\n";
string signedHeaders =
string.Join(";", headers.Select(x => x.Key.ToLowerInvariant() ));
// Task 1: Create a Canonical Request For Signature Version 4
var canonicalRequest = method + '\n' + canonicalUri + '\n' + canonicalQueryString +
'\n' + canonicalHeaders + '\n' + signedHeaders + '\n' + hashedRequestPayload;
var hashedCanonicalRequest = HexEncode(Hash(ToBytes(canonicalRequest)));
// Task 2: Create a String to Sign for Signature Version 4
// StringToSign = Algorithm + '\n' + RequestDate + '\n' + CredentialScope + '\n' + HashedCanonicalRequest
var stringToSign = string.Format("{0}\n{1}\n{2}\n{3}", algorithm, requestDate, credentialScope,
hashedCanonicalRequest);
// Task 3: Calculate the AWS Signature Version 4
// HMAC(HMAC(HMAC(HMAC("AWS4" + kSecret,"20130913"),"eu-west-1"),"tts"),"aws4_request")
byte[] signingKey = GetSignatureKey(SecretKey, dateStamp, regionName, serviceName);
// signature = HexEncode(HMAC(derived-signing-key, string-to-sign))
var signature = HexEncode(HmacSha256(stringToSign, signingKey));
// Task 4: Prepare a signed request
// Authorization: algorithm Credential=access key ID/credential scope, SignedHeadaers=SignedHeaders, Signature=signature
var authorization =
string.Format("{0} Credential={1}/{2}/{3}/{4}/aws4_request, SignedHeaders={5}, Signature={6}",
algorithm, AccessKey, dateStamp, regionName, serviceName, signedHeaders, signature);
// Send the request
string endpoint = "https://" + host; // + canonicalUri ;
var webRequest = WebRequest.Create(endpoint);
webRequest.Method = method;
webRequest.Timeout = 20000;
webRequest.ContentType = contentType;
webRequest.Headers.Add("X-Amz-Date", requestDate);
webRequest.Headers.Add("Authorization", authorization);
webRequest.Headers.Add("X-Amz-Target", x_amz_target_header);
webRequest.ContentLength = bytes.Length;
using (Stream newStream = webRequest.GetRequestStream())
{
newStream.Write(bytes, 0, bytes.Length);
newStream.Flush();
}
var response = (HttpWebResponse)webRequest.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (var streamReader = new StreamReader(responseStream))
{
string res = streamReader.ReadToEnd();
return res;
}
}
}
return null;
}
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));
}
}
}