HTTP Authentification and CGI/Servlet

1. Identify yourself using HTTP Authentification

import java.net.*;
import java.io.*;

public class TestAuth {

  public static void main (String args[]){
    /*
    ** args[0]  is the URL protected
    ** args[1]  is the username
    ** args[2]  is the password
    */
    try {
      BufferedReader in = new BufferedReader(
          new InputStreamReader
             (openURLForInput(new URL(args[0]), args[1], args[2])));
      String line;
      while ((line = in.readLine()) != null) {
          System.out.println(line);
          }
    }
    catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static InputStream openURLForInput
       (URL url, String uname, String pword)
       throws IOException
  {
    URLConnection conn = url.openConnection();
    conn.setDoInput (true);
    conn.setRequestProperty ("Authorization",
       userNamePasswordBase64(uname,pword));
    conn.connect ();
    return conn.getInputStream();
  }

  public static String userNamePasswordBase64
       (String username, String password)
  {
    return "Basic " + base64Encode (username + ":" + password);
  }

  private final static char base64Array [] = {
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
      'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
      'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
      'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
      'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
      'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
      'w', 'x', 'y', 'z', '0', '1', '2', '3',
      '4', '5', '6', '7', '8', '9', '+', '/'
  };



  private static String base64Encode (String string)    {
    String encodedString = "";
    byte bytes [] = string.getBytes ();
    int i = 0;
    int pad = 0;
    while (i < bytes.length) {
      byte b1 = bytes [i++];
      byte b2;
      byte b3;
      if (i >= bytes.length) {
         b2 = 0;
         b3 = 0;
         pad = 2;
         }
      else {
         b2 = bytes [i++];
         if (i >= bytes.length) {
            b3 = 0;
            pad = 1;
            }
         else
            b3 = bytes [i++];
         }
      byte c1 = (byte)(b1 >> 2);
      byte c2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
      byte c3 = (byte)(((b2 & 0xf) << 2) | (b3 >> 6));
      byte c4 = (byte)(b3 & 0x3f);
      encodedString += base64Array [c1];
      encodedString += base64Array [c2];
      switch (pad) {
       case 0:
         encodedString += base64Array [c3];
         encodedString += base64Array [c4];
         break;
       case 1:
         encodedString += base64Array [c3];
         encodedString += "=";
         break;
       case 2:
         encodedString += "==";
         break;
       }
      }
      return encodedString;
  }
}

A better alternative is the Authenticator class.

NOTE: a simple explanation about the base64 encoding principle is shown in this How-to.

An alternative way to Base64 encoding is to use the Base64 class in the sun.misc.* package.

sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
String encodedUserPwd =
  encoder.encode("domain\\username:password".getBytes());
con.setRequestProperty("Proxy-Authorization", "Basic " + encodedUserPwd);

Use of the sun.* package is “discouraged” by sun and not formally supported. Those classes can be missing in your JDK release.

2. Talk to a CGI/Servlet

From the client point of view, there is no difference talking to CGI or Servlet. There is two ways to send a request to a CGI. The GET method contains encoded parameters in the URL. A typical URL talking to CGI using the GET method would be:

new URL("http://www.server.com/cgi-bin/acgi.pl?name=real&site=java+howto");

Here we calling a script called aCGI.pl (a PERL script) passing the parameters name and site. Parameters are encoded, spaces are changed to “+” and special character to hexadecimal using a 3-letter escape sequence. Each parameter is delimited by the character “&”. Habitually the encoding is done through the static method encode of the java.net.URLencoder class.

String theCGI = "http://www.server.com/cgi-bin/aCGI.pl?";
String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL cgiurl = new URL(thecgi + encoded);

Once the URL is constructed, you call the CGI using the showDocument method (Applet).

getAppletContext().showDocument(cgiurl);

The CGI will process the result and produce a page to be displayed.

The POST method allows the programmer to manipulate the data received from the CGI. First a connection is made to the CGI, an OutputStream is open to send the parameters (if any). Then InputStream is created to receive the result.

String theCGI = "http://www.server.com/cgi-bin/aCGI.pl";
String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL CGIurl = new URL(theCGI);

URLConnection c = CGIurl.openConnection();
c.setDoOutput(true);
c.setUseCaches(false);
c.setRequestProperty("content-type","application/x-www-form-urlencoded");
DataOutputStream out = new DataOutputStream(c.getOutputStream());
out.writeBytes(encoded);
out.flush(); out.close();

BufferedReader in =
   new BufferedReader(new InputStreamReader(c.getInputStream());

String aLine;
while ((aLine = in.readLine()) != null) {
   // data from the CGI
   System.out.println(aLine);
}

You can’t do some output then some input and do again some output. You must do all the output and then the input. There is no “dialog” between the client and the server. The client make a request and the server send back the result and close the connection.

Done! Happy Coding!

Related posts:

Java Program to Generate Date Between Given Range
Java Program to Implement Sieve Of Eratosthenes
Hashing a Password in Java
Java Program to Implement Word Wrap Problem
Java Program to Construct a Random Graph by the Method of Random Edge Selection
Java Program to Perform the Unique Factorization of a Given Number
Converting a Stack Trace to a String in Java
Limiting Query Results with JPA and Spring Data JPA
How to Get All Spring-Managed Beans?
Semaphore trong Java
Java Program to Implement LinkedHashSet API
Spring Boot - Eureka Server
Sending Emails with Java
JWT – Token-based Authentication trong Jersey 2.x
Java Program to Implement Hash Tree
Case-Insensitive String Matching in Java
ETags for REST with Spring
Flattening Nested Collections in Java
Java Program to Compute Discrete Fourier Transform Using the Fast Fourier Transform Approach
Java Program to Implement the String Search Algorithm for Short Text Sizes
Java Program to Give an Implementation of the Traditional Chinese Postman Problem
Java Program to Implement String Matching Using Vectors
Getting Started with Forms in Spring MVC
New in Spring Security OAuth2 – Verify Claims
Jackson – Bidirectional Relationships
Phân biệt JVM, JRE, JDK
Hashtable trong java
Notify User of Login From New Device or Location
Tiêu chuẩn coding trong Java (Coding Standards)
SOAP Web service: Authentication trong JAX-WS
How to Read a Large File Efficiently with Java
Java Program to Create a Minimal Set of All Edges Whose Addition will Convert it to a Strongly Conne...