The following sample application gets the IP address of the end user and sends the IP address to the IP2Location.io IP Geolocation API. The API returns a JSON string containing the country code that corresponds with the end user’s IP address. The application then evaluates whether the value returned by IP2Location.io API matches the blocked country code. If the end user’s country is blocked, the application will show 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.
/* * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. */ <%@ Page Language="C#" AutoEventWireup="true" Inherits="CloudFront.cloudfront" %> <!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>Example of Country Access Control</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" %> <%@ Import Namespace="System.Text.RegularExpressions" %> <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}}}}}}}]}}"; // IP2Location.io API key to be passed to geolocation service call private const string API_KEY = "IP2Location.io key"; // IP2Location.io API // {0} = IP Address and {1} = IP2Location.io API key private const string APIURL = "https://api.ip2location.io/?ip={0}&key={1}"; // Setting array of countries to block private static readonly string[] BLOCKED_COUNTRIES = new string[] {"VN"}; private const string BLOCKED_MSG = "You are not authorized to view the content because you're visiting from '{0}'."; // Get IP address of visitor and determine the country code private string GetCountryCodeFromIP() { // Get IP address from HTTP_X_FORWARDED_FOR string ip_address = this.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; // If HTTP_X_FORWARDED_FOR does not exists or no IP address if (string.IsNullOrEmpty(ip_address)) { // Get UserHostAddress. ip_address = Request.UserHostAddress; } else { // Get the last item in the list. ip_address = ip_address.Split(',').Last().Trim(); } // Format the API_URL with the IP address and API key var API_URL = string.Format(APIURL, Server.UrlEncode(ip_address), Server.UrlEncode(API_KEY)); // Setting up connection to geolocation service try { var request = HttpWebRequest.Create(APIURL); var response = request.GetResponse().GetResponseStream(); var reader = new StreamReader(response); var strRes = reader.ReadToEnd(); reader.Close(); Regex r = new Regex(@"""country_code"":""([^\""]+)"""); Match m = r.Match(strRes); if (m.Success) { return m.Groups[1].Value; } return "-"; } catch(Exception ex) { // If error occur in making the web request. this.Response.Write(API_URL + "<br><br>"); this.Response.Write(ex.Message); this.Response.End(); } return null; } // Creates a signed URL which expires in 1 minute 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; } // Display Cloud Front signed URL and image if user is not blocked and display country blocked message if user is blocked public string GetContent() { var country = GetCountryCodeFromIP(); if (!BLOCKED_COUNTRIES.Contains(country)) { // Signed URL with Cloud Front if country code is not blocked var url = GetSignedURL("CloudFront URL"); var img = "<img src='{0}' />"; return String.Format(img, url); } else { // Returns a string of message if country code is blocked return string.Format(BLOCKED_MSG, country); } } </script>