| Did this page help you? Yes No Tell us about it... |
The following sample application gets the IP address of the end user and sends the IP address to Digital Element. Digital Element returns the country code (in XML format) that corresponds with the end user's IP address. The application parses the XML and evaluates whether the value returned by Digital Element matches the blocked country code. If the end user's country is blocked, the application displays a message to that effect. If the end user's country is not blocked, the application creates a signed URL that expires in one minute, performs the substitutions necessary to ensure that the URL doesn't include any invalid characters, and redirects the user's browser to the signed URL.
<%@ Page Language="C#" AutoEventWireup="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <%=GetContent()%> </div> </form> </body> </html> <%@ Import Namespace="System.Linq" %> <%@ Import Namespace="System.Xml.Linq" %> <%@ Import Namespace="System.Security.Cryptography" %> <%@ Import Namespace="System.Net" %> <%@ Import Namespace="System.IO" %> <script runat="server"> // Key pair ID for the CloudFront key pair private const string KEYPAIR_ID = "CloudFront key pair ID"; // Private key for the CloudFront key pair. // The value is derived from opensslkey. private const string PRIVATE_KEY = "private key"; // JSON policy statement used in the expiring URL private const string POLICY = "{{\"Statement\":[{{\"Resource\":\"{0}\",\"Condition\":{{\"DateLessThan\":{{\"AWS:EpochTime\":{1}}}}}}}]}}"; // Digital Element user token to be passed to geolocation service call private const string USERTOKEN = "Digital Element user token"; private const string GEOAPIURL = "Digital Element URL"; // GEO IP service URL with parameters: // {0} = User Token and {1} = IP Address private const string SERVICEURL = GEOAPIURL + "?u={0}&ip={1}"; // Array of countries to block private static readonly string[] COUNTRIES_TO_BLOCK = new String[] {"US"}; private const string BLOCKED_MSG = "Your access to this content is blocked because you're visiting from'{0}'."; /// <summary> /// Returns the IP address coming from the request object. /// </summary> /// <returns>The IP address for the request.</returns> private string GetOriginIpAddress() { // .NET provides Request.UserHostAddress to get the // remote IP address, but this could be the IP address of the // last proxy in a chain, for example, an Elastic Load Balancer. // Instead, use the HTTP_X_FORWARDED_FOR header if one exists. string forwardedIpAddresses = this.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (string.IsNullOrEmpty(forwardedIpAddresses)) { // Simply return the UserHostAddress. return Request.UserHostAddress; } else { // Get the last item in the list. return forwardedIpAddresses.Split(',').Last().Trim(); } } /// <summary> /// This function returns the country code /// associated with the IP address in the request object. /// </summary> /// <returns>The country code for the request.</returns> private string GetCountryCodeFromIP() { var ipAddress = GetOriginIpAddress(); var serviceURL = String.Format(SERVICEURL, Server.UrlEncode(USERTOKEN), Server.UrlEncode(ipAddress)); try { var xDoc = XDocument.Load(serviceURL); var res = (from w in xDoc.Descendants("response") select w).First(); return res.Attribute("edge-two-letter-country").Value.ToUpper(); } catch(Exception ex) { // There was an error in making the web request. this.Response.Write(serviceURL + "<br><br>"); this.Response.Write(ex.Message); this.Response.End(); } return null; } /// <summary> /// This function returns a signed URL that will expire in 1 minute. /// For more information, see "Create a URL Signature Using C# and the /// .NET Framework" in the Amazon CloudFront Developer Guide: /// http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/CreateSignatureInCSharp.html?r=4472 /// </summary> /// <param name="resourceUrl"></param> /// <returns></returns> private string GetSignedURL(string resourceUrl) { // Compute expiration date. var endTimeSpanFromNow = new TimeSpan(0, 1, 0); var intervalEnd = (DateTime.UtcNow.Add(endTimeSpanFromNow)) - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); var endTimestamp = (int)intervalEnd.TotalSeconds; // Timestamp must be a whole number var expires = endTimestamp.ToString(); var strPolicy = string.Format(POLICY, resourceUrl, expires); // Encrypt the policy. var bufferPolicy = Encoding.ASCII.GetBytes(strPolicy); var cryptoSHA1 = new SHA1CryptoServiceProvider(); bufferPolicy = cryptoSHA1.ComputeHash(bufferPolicy); var providerRSA = new RSACryptoServiceProvider(); providerRSA.FromXmlString(PRIVATE_KEY); var rsaFormatter = new RSAPKCS1SignatureFormatter(providerRSA); rsaFormatter.SetHashAlgorithm("SHA1"); var signedPolicyHash = rsaFormatter.CreateSignature(bufferPolicy); var strSignedPolicy = System.Convert.ToBase64String(signedPolicyHash); // Build the query string with the expiration, policy signature, // and CloudFront key pair ID. var queryString = "Expires={0}&Signature={1}&Key-Pair-Id={2}"; queryString = String.Format(queryString, Server.UrlEncode(expires), Server.UrlEncode(strSignedPolicy), Server.UrlEncode(KEYPAIR_ID)); var urlString = resourceUrl + "?" + queryString; return urlString; } /// <summary> /// Return a message saying this is blocked because of your country, or /// return an image tag. /// </summary> /// <returns></returns> public string GetContent() { var country = GetCountryCodeFromIP(); if (COUNTRIES_TO_BLOCK.Contains(country)) { // The country returned from the call to the geolocation service // is listed in the array of blocked countries. return string.Format(BLOCKED_MSG, country); } else { // The country returned from the call to the geolocation service // is NOT listed in the array of blocked countries // Get a CloudFront signed URL for the content and display it. var url = GetSignedURL("CloudFront URL"); var img = "<img src='{0}' />"; return String.Format(img, url); } } </script>