Configure Country Access Control in CloudFront Using Java

In this example, we demonstrate you on how to obtain country code that is associated with an end user’s IP address. For all users except VN users (Vietnam), users are allowed to access the CloudFront content where distribution is allowed. In this case, the GetCountryCodeServlet.java will request SignedUrl.java to create a signed URL that the end user can use to access a file in the CloudFront distribution.

GetCountryCodeServlet.java

GetCountryCodeServlet.java calls GetIP2LocationCountryCode.java, which is shown later in this article, to ask IP2Location.io IP Geolocation API for the country code that is associated with an end user’s IP address. If the country code is not VN (Vietnam), GetCountryCodeServlet.java calls SignedUrl.java to create a signed URL that the end user can use to access a file in the CloudFront distribution.

/*
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
 
import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringTokenizer;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GetCountryCodeServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;
 
   final String GEOAPIKEY = "IP2Location.io API key";
   final String PATHTODER = "path to .der file";
   final String KEYPAIRID ="CloudFront key pair ID";
   final String HTTPORHTTPS = "https";
   final String CFDISTRIBUTION = "dxxxx.cloudfront.net";
   final String CFPATH = "CloudFront URL for file";
   // date and time that CloudFront's signed URL expires,
   // in Coordinated Universal Time
   final String EXPIRES = "2012-11-14T22:20:00.000Z";
   final String COUNTRYBLOCKED="VN";
 
   // This function will determine whether the end user have the permission to access the content or not
   // based on the country code return by end user's IP address
   protected void getIP(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
      PrintWriter out = response.getWriter();
      StringTokenizer st = null;
      String enduser_ip = null;
 
      // Retrieving end user's IP address from X-Forwarded-IP header
      String headers = request.getHeader("X-FORWARDED-FOR");
 
      if (headers!= null){
         st = new StringTokenizer(headers,",");
 
         while (st.hasMoreTokens()) {
             enduser_ip = st.nextToken();
         }
      }
 
      // Retrieving the end user's IP address if X-Forwarded-IP header does not exist
 
      if (enduser_ip == null)
        enduser_ip = request.getRemoteAddr();
 
      try {
         GetIP2LocationCountryCode country = new GetIP2LocationCountryCode(GEOAPIKEY, enduser_ip);
 
         if ( !country.getCountry().equalsIgnoreCase(COUNTRYBLOCKED)){
 
            SignedUrl myApp = new SignedUrl(KEYPAIRID,PATHTODER);
            System.out.println(myApp.getSignedHash(HTTPORHTTPS,CFDISTRIBUTION,CFPATH,EXPIRES));
         }else {
            System.out.println("Sorry, you do not have permission to access the content.");
         }
      } catch (Exception e1) {
         e1.printStackTrace();
      }
   }
}

GetIP2LocationCountryCode.java

GetIP2LocationCountryCode.java sends IP2Location.io API a request that includes an end user’s IP address. The return value is a country code.

/*
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
 
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GetIP2LocationCountryCode {
 
    private static String apiKey;
    private static String ip_address;
 
    GetIP2LocationCountryCode(String myapiKey, String ip){
        apiKey = myapiKey;
        ip_address = ip;
    }
 
    // This function will return country code by calling IP2Location.io API after retrieving
    // end user's IP address
    public String getCountry() throws Exception {
        // URL string for IP2Location.io API
        String APIURL = "https://api.ip2location.io/?ip="+ip_address+"&key="+apiKey;
 
        // Open connection to IP2Location.io API
        URL url = new URL(APIURL);
        URLConnection urlConn = url.openConnection();
 
        urlConn.setUseCaches(false);
 
        InputStreamReader in = new InputStreamReader((InputStream) urlConn.getContent());
        BufferedReader buff = new BufferedReader(in);
 
        String res = buff.readLine();
        Pattern pattern = Pattern.compile(".+\"country_code\":\"([^\"]+)\".+");
        Matcher matcher = pattern.matcher(res);
        if (matcher.matches()) {
           return matcher.group(1);
        }
        return "-";
    }
}

SignedUrl.java

SignedUrl.java creates a signed URL that the end user can use to access a file in the CloudFront distribution if the country is not blocked.

/*
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
 
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.Security;
import java.text.ParseException;
 
import org.jets3t.service.CloudFrontService;
import org.jets3t.service.CloudFrontServiceException;
import org.jets3t.service.utils.ServiceUtils;
 
public class SignedUrl {
   private static String keyPairId;
   private static String privateKeyFilePath;
 
   SignedUrl(String mykeyPairId, String myprivateKeyFilePath){
      keyPairId = mykeyPairId;
      privateKeyFilePath = myprivateKeyFilePath;
   }
 
   public String getSignedHash(String protocol, String cfDistribution, String objectUri, String expTime) throws FileNotFoundException, IOException,
   CloudFrontServiceException, ParseException{
 
   Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
 
      byte[] derPrivateKey = ServiceUtils.readInputStreamToBytes(new FileInputStream(privateKeyFilePath));
 
   String signedUrlCanned = CloudFrontService.signUrlCanned(
       protocol+ "://" + cfDistribution + "/" + objectUri,
       keyPairId,
       derPrivateKey,
       ServiceUtils.parseIso8601Date(expTime)
       );
 
   return signedUrlCanned;
   }
}

Was this article helpful?

Related Articles