Merhaba bu yazımda sizlere Amazon AWIS servisi ile web sayfalarının trafiğini nasıl elde edeceğimizi anlatacağım.
Öncellikle Amazon sayfasında hesap açmamız ve açtığımız hesapta servisimizi kullanacak olan bir kullanıcı tanımlayıp daha sonrasında kullanıcı için Access Key üretmemiz gerekiyor. Ürettiğimiz Access Key ide kodumuzda kullanacağız. Amazonun console panelinde bir kullanıcı üretip, role olarak admin, ve bir access key oluşturduysak şimdi .net tarafında kodumuza başlayalım.
Kütüphane kodumuz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Globalization; using System.Linq; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using System.Web; namespace AWIS { namespace Aws4RequestSigner { public class AWS4RequestSigner { private readonly string _access_key; private readonly string _secret_key; private readonly SHA256 _sha256; private const string algorithm = "AWS4-HMAC-SHA256"; public AWS4RequestSigner(string accessKey, string secretKey) { if (string.IsNullOrEmpty(accessKey)) { throw new ArgumentOutOfRangeException(nameof(accessKey), accessKey, "Not a valid access_key."); } if (string.IsNullOrEmpty(secretKey)) { throw new ArgumentOutOfRangeException(nameof(secretKey), secretKey, "Not a valid secret_key."); } _access_key = accessKey; _secret_key = secretKey; _sha256 = SHA256.Create(); } private string Hash(string stringToHash) { var result = _sha256.ComputeHash(Encoding.UTF8.GetBytes(stringToHash)); return ToHexString(result); } private static byte[] HmacSHA256(byte[] key, string data) { var hashAlgorithm = new HMACSHA256(key); return hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(data)); } private static byte[] GetSignatureKey(string key, string dateStamp, string regionName, string serviceName) { byte[] kSecret = Encoding.UTF8.GetBytes("AWS4" + key); byte[] kDate = HmacSHA256(kSecret, dateStamp); byte[] kRegion = HmacSHA256(kDate, regionName); byte[] kService = HmacSHA256(kRegion, serviceName); byte[] kSigning = HmacSHA256(kService, "aws4_request"); return kSigning; } private static string ToHexString(byte[] array) { var hex = new StringBuilder(array.Length * 2); foreach (byte b in array) { hex.AppendFormat("{0:x2}", b); } return hex.ToString(); } public async Task<HttpRequestMessage> Sign(HttpRequestMessage request, string service, string region) { if (string.IsNullOrEmpty(service)) { throw new ArgumentOutOfRangeException(nameof(service), service, "Not a valid service."); } if (string.IsNullOrEmpty(region)) { throw new ArgumentOutOfRangeException(nameof(region), region, "Not a valid region."); } if (request == null) { throw new ArgumentNullException(nameof(request)); } if (request.Headers.Host == null) { request.Headers.Host = request.RequestUri.Host; } var t = DateTimeOffset.UtcNow; var amzdate = t.ToString("yyyyMMddTHHmmssZ"); request.Headers.Add("x-amz-date", amzdate); var datestamp = t.ToString("yyyyMMdd"); var canonical_request = new StringBuilder(); canonical_request.Append(request.Method + "\n"); canonical_request.Append(request.RequestUri.AbsolutePath + "\n"); var canonicalQueryParams = GetCanonicalQueryParams(request); canonical_request.Append(canonicalQueryParams + "\n"); var signedHeadersList = new List<string>(); foreach (var header in request.Headers.OrderBy(a => a.Key.ToLowerInvariant())) { canonical_request.Append(header.Key.ToLowerInvariant()); canonical_request.Append(":"); canonical_request.Append(string.Join(",", header.Value.Select(s => s.Trim()))); canonical_request.Append("\n"); signedHeadersList.Add(header.Key.ToLowerInvariant()); } canonical_request.Append("\n"); var signed_headers = string.Join(";", signedHeadersList); canonical_request.Append(signed_headers + "\n"); var content = ""; if (request.Content != null) { content = await request.Content.ReadAsStringAsync(); } var payload_hash = Hash(content); canonical_request.Append(payload_hash); var credential_scope = $"{datestamp}/{region}/{service}/aws4_request\n"; var string_to_sign = $"{algorithm}\n{amzdate}\n{credential_scope}\n" + Hash(canonical_request.ToString()); var signing_key = GetSignatureKey(_secret_key, datestamp, region, service); var signature = ToHexString(HmacSHA256(signing_key, string_to_sign.Replace("aws4_request\n", "aws4_request"))); request.Headers.TryAddWithoutValidation("Authorization", $"{algorithm} Credential={_access_key}/{credential_scope.TrimEnd()}, SignedHeaders={signed_headers}, Signature={signature}"); // request.Headers.Accept = System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/xml"); return request; } private static string GetCanonicalQueryParams(HttpRequestMessage request) { var querystring = HttpUtility.ParseQueryString(request.RequestUri.Query); var keys = querystring.AllKeys.OrderBy(a => a).ToArray(); var queryParams = keys.Select(key => $"{key}={querystring[key]}"); var canonicalQueryParams = string.Join("&", queryParams); return canonicalQueryParams; } } } } |
Aşağıdaki kodumuzda kütüphanemiz ile AWIS e bağlanıp xml data çeken kodumuz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
static async Task<string> GetXmlValueFromAWIS(string p) { string AWSAccessKeyId = "your key"; string AWSSecret = "your key"; var signer = new AWS4RequestSigner(AWSAccessKeyId, AWSSecret); var request = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri("https://awis.us-west-1.amazonaws.com/api?" + p) }; request = await signer.Sign(request, "awis", "us-west-1"); var client = new HttpClient(); client.Timeout = new TimeSpan(0, 10, 0); var response = await client.SendAsync(request); var responseStr = await response.Content.ReadAsStringAsync(); return responseStr; } |
dönen Xml datayı parse edip , dataliste dönüştürmek için
1 2 3 4 |
XNamespace aws = "http://awis.amazonaws.com/doc/2005-07-11"; XElement xe = XElement.Load(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(value))); var result = from cc in xe.Element(aws + "Response").Element(aws + "TrafficHistoryResult").Element(aws + "Alexa").Element(aws + "TrafficHistory").Element(aws + "HistoricalData").Elements(aws + "Data") select new { Date = cc.Element(aws + "Date").Value, PerMillion = cc.Element(aws + "PageViews").Element(aws + "PerMillion").Value, PerUser = cc.Element(aws + "PageViews").Element(aws + "PerUser").Value }; |