Authentication framework Design

 

Most Internet and Intranet applications needs to have dynamic authentication model.

Depending upon the  applications data source might be different.

Application-controlled authentication and access control require the following actions

 

For this action I have defined the authentication interface : 

import com.sfg.authenticate.exception.*;

public interface Authenticate  {

      /**
      * Verify the Login and Password
      *
      * @param 	userid  login id of the user
      * @param  password passowrd of the user
      * @return 	Information about the user UserInfo
      * @throws UnsupportedOperationException if function is not supported
      * @throws AuthenticationFailed  if user/password is not valid.
      *
      * @see com.sfg.authenticate.UserInfo
      */

	public UserInfo authenticate( String userid, String passwd )
          throws UnsupportedOperationException, AuthenticationException;

	/**
	* Check the UserId in the database
        * @param 	userid  login id of the user
        * @return boolean if valid user id true, otherwise false
        **/

	public boolean checkUserId( String userid )
           throws UnsupportedOperationException, AuthenticationException;

	/**
	*  Add New User into database
	**/

	public boolean addUser( UserInfo userInfo )
        throws UnsupportedOperationException, AuthenticationException;

	/**
	** Remove the User from the database
	**/
	public boolean removeUser( String userid )
         throws UnsupportedOperationException, AuthenticationException;

	/**
	** Modify the User Info like password change, email or name
	**/
	public boolean updateUser( String userid, UserInfo userInfo )
                throws UnsupportedOperationException, AuthenticationException;

} 
 

We have to implement this interface for each data source. Depending upone the data source implement all or some method. For example JDBC data source we can implement all the methods, where as WINDOWS datasource we implement only authenticate method. But all implementation uses the UserInfo class

 

package com.sfg.authenticate;

import java.io.*;
import java.util.*;


/**
 * This class contains information about a user. It's used to show
 * how a bean can be used to validate user input and format output
 * so it's suitable for HTML.
 *
 * @author Sundaram Ramasamy 
 * @version 1.0
 */
public class UserInfo implements Serializable, Cloneable {

    // Properties
   private String userid="";
   private String password="";
   private String confPassword="";
   private String lname="";
   private String fname="";
   private String email="";

   private boolean isInitialized;
   private Hashtable errors;

    /**
     *  Constructor
     */
    public UserInfo() {
     errors = new Hashtable();
    }

    /**
     * Returns the userid property value
     */
    public String getUserid() {
	return (userid == null ? "" : userid);
    }

    /**
	 * Returns the passwd property value
    */
    public String getPassword() {
	return (password == null ? "" : password);
    }
   /**
    * Returns the passwd property value
    */
    public String getConfPassword() {
	return (password == null ? "" : password);
    }


    /**
     * Returns the First name property value
    */
    public String getFname() {
      return (fname == null ? "" : fname);
    }


   /**
   * Returns the Last name property value
   */
   public String getLname() {
    return (lname == null ? "" : lname);
   }

    /**
     * Returns the emailAddr property value
     */
    public String getEmail() {
	return (email == null ? "" : email);
    }

    /**
     * Returns the emailAddr property value,
     * with all HTML special characters converted
     * to HTML character entities
     */
    public String getEmailAddrFormatted() {
	return this.email;
    }

    /**
     * Sets the emailAddr property value, if it's
     * valid
     */
    public void setEmail(String emailAddr) {
	isInitialized = true;
	this.email = emailAddr;
    }


    /**
     * Sets the userid property value
     */
    public void setUserid(String userid) {
	isInitialized = true;
	this.userid = userid;
    }

  /**
   * Sets password property value
   */
    public void setPassword(String password) {
	this.password = password;
    }

  /**
   * Sets password property value
   */
    public void setConfPassword(String confPassword) {
	this.confPassword = confPassword;
    }


  /**
   * Sets fname property value
   */
    public void setFname(String fname) {
	this.fname = fname;
    }

    /**
     * Sets lname property value
     */
    public void setLname(String lname ) {
	this.lname = lname;
    }


    /**
     * Returns true if all property values have valid values
     * (they are only set if the value is valid).
     */
   public boolean validate() {
	boolean allOk = true;

      if( userid == null || userid.equals("" ) ) {
	errors.put("userid", "Please enter the User ID" );
	userid="";
	allOk = false;
       }

    if( password == null || password.equals("")  ) {
	errors.put("password", "Please enter a valid password" );
	password= "";
	allOk = false;
    }

    if(confPassword == null || confPassword.equals("") || !password.equals( confPassword )) {
	errors.put("cpassword", "Please confirm your password");
	confPassword="";
	allOk = false;
    }

    if(fname == null ||  fname.equals("") ) {
	errors.put( "fname", "Please enter your first name");
	allOk = false;
    }

    if( lname == null || lname.equals("") ) {
	errors.put( "lname", "Plese enter your last name");
	lname="";
	allOk = false;
    }

    if( email == null || email.equals("") || ( email.indexOf('@') == -1 ) ) {
	errors.put("email", "Please enter a valid email address");
	allOk = false;
      }


    return allOk;
  }

  public String getErrorMsg( String s ) {
	String errorMsg = (String) errors.get( s.trim());
    return (errorMsg == null) ? "": errorMsg;
  }

  /**
   * Remove the Error Message
   */
   public void clearErrors() {
	errors.clear();
  }


  public void setErrors( String key, String msg ) {
  	errors.put(key, msg);
  }

  public String toString() {
    StringBuffer buf = new StringBuffer();
      buf.append("User Id : ").append(this.userid).append("\n")
      .append("Password :" ).append(this.password).append("\n")
      .append("First Name ").append(fname).append("\n")
      .append("Last Name").append(lname).append("\n")
      .append("Email").append(email);
      return buf.toString();
  }
  

  /**
   * Make the Copy of this object
   */
  public Object mkCopy () throws CloneNotSupportedException {
    return this.clone();
  }

}
 

The Following code listing show the sample implementation of JDBC Data source.
/********************************************************************
 *    Title:        Web site Form based authentication
 * 	Description:  The Purpose of this project is to authenticate the web user using different data source.
 * -- Database 
 * Copyright:    Copyright (c) 2001
 * Date :  08/22/2001
 * @author Sundaram Ramasamy 
 * @version 1.0
 *
 *******************************************************************/

package com.sfg.authenticate.sql;

import java.io.*;
import java.util.*;
import java.sql.*;

import com.sfg.authenticate.*;
import com.sfg.authenticate.exception.*;

public class SQLAuthenticate  implements Authenticate  {

    private String dbURL, user, password;
    private Connection con = null;

    /**
     * Constructor Load the driver and create the database connection
     * @param dbURL Database connection URL
     * @param database user name
     * @param user password
     * @param Driver Class Name
     * @throws SQLException, ClassNotFoundException
     */
    public SQLAuthenticate(String dbURL, String user, String password,
	String driverClassName) throws SQLException, ClassNotFoundException {

	// Load the specified driver class
	Class.forName(driverClassName);

	this.dbURL = dbURL;
	this.user = user;
	this.password = password;

        // Create the Database connection
	con= DriverManager.getConnection(dbURL, user, password);
    }

    /**
      *   Verify the Login and Password
      *   @param userid
      *   @param password
      *   @return User information
    **/
    public UserInfo authenticate( String userid, String passwd )
            throws AuthenticationException {

       UserInfo userInfo = null;
     try {
	if( con == null ) {
	    con= DriverManager.getConnection(dbURL, user, password);
	}

	ResultSet rset = null;

	StringBuffer sql = new StringBuffer();
	sql.append("SELECT * FROM USERINFO ")
	    .append("WHERE USERID = ? AND PASSWORD = ?");

     // Prepare a statement to update the ENAME column at a given ROWID

      PreparedStatement pstmt =
	con.prepareStatement (sql.toString());

      pstmt.setString(1, userid);
      pstmt.setString(2, passwd);

      rset = pstmt.executeQuery();

      if( rset.next() ) {
	  userInfo = new UserInfo();
	  userInfo.setUserid( rset.getString(1) );
	  userInfo.setPassword( rset.getString(2) );
	  userInfo.setLname( rset.getString(4) );
	  userInfo.setFname( rset.getString(3 ) );
	  userInfo.setEmail( rset.getString(5) );
      }
      pstmt.close();

    } catch( SQLException ex ) {
        throw new AuthenticationFailed( ex.toString(), ex);
    } finally {
      if( userInfo == null ){
        throw new AuthenticationFailed("Invalid User Name/Password");
      }
      return userInfo;
    }
  }

  /**
   * Check the user id alread in the database
   * @param userid
   * @return success/Failer
   */
  public boolean checkUserId( String userid ) throws AuthenticationException {
    boolean retval = false;
    try {
      if( con == null ) {
	    con= DriverManager.getConnection(dbURL, user, password);
      }
      ResultSet rset = null;

      StringBuffer sql = new StringBuffer();
      sql.append("SELECT count(*) FROM USERINFO ")
	    .append("WHERE USERID = ?");

     // Prepare a statement to update the ENAME column at a given ROWID

      PreparedStatement pstmt =
	con.prepareStatement (sql.toString());

      pstmt.setString(1, userid);

      rset = pstmt.executeQuery();
      rset.next();
      int row = rset.getInt(1);

      if( row != 0 ) {
	retval = true;
      }
      pstmt.close();

    } catch( Exception ex ) {
      throw new AuthenticationException(ex.toString(), ex);
    }

    return retval;
   }


  /**
    *  Add New User into database
  **/

    public boolean addUser( UserInfo userInfo ) throws AuthenticationException {
      boolean retval = false;

      try {
        if( con == null ) {
	    con= DriverManager.getConnection(dbURL, user, password);
	 }

      PreparedStatement insstmt =
		 con.prepareStatement (" insert into userinfo values(?, ?, ?, ?,? )");

      insstmt.setString(1, userInfo.getUserid());
      insstmt.setString(2, userInfo.getPassword());
      insstmt.setString(3, userInfo.getLname());
      insstmt.setString(4, userInfo.getFname() );
      insstmt.setString(5, userInfo.getEmail() );

      int row = insstmt.executeUpdate();

      if( row != 0 ) {
	retval = true;
	}

      if( con.getAutoCommit() !=  true) {
        con.commit();
      }
      insstmt.close();
      } catch( Exception ex ) {
        throw new AuthenticationException(ex.toString());
      }
      return retval;
  }

  /**
   * Remove the user from the database
   * @param userid to remove
   * @return success/fail
   */
    public boolean removeUser( String userid ) throws AuthenticationException {
	boolean retval = false;

    try {
      if( con == null ) {
	con= DriverManager.getConnection(dbURL, user, password);
     }

      ResultSet rset = null;

      StringBuffer sql = new StringBuffer();
      sql.append("DELETE FROM USERINFO ")
	    .append("WHERE USERID = ?");

      PreparedStatement pstmt =	con.prepareStatement (sql.toString());
      pstmt.setString(1, userid);
      int row = pstmt.executeUpdate ();

      if( row != 0 ) {
	retval = true;
      }
      pstmt.close();

    } catch( Exception ex ) {
      throw new AuthenticationException( ex.toString());
    }
    return retval;
}

  /**
    * Modify the User Info like passwd change, email or name
    * @param user id
    * @param User Info to update
    * @return success/failure
    * throws AuthenticationException
  **/
    public boolean updateUser( String userid, UserInfo userInfo )
              throws AuthenticationException {

       boolean retval = false;

      try {
	if( con == null ) {
	  con= DriverManager.getConnection(dbURL, user, password);
	}

	StringBuffer sql = new StringBuffer();
	// Use UPDATE statement
	sql.append("UPDATE USERINFO SET ")
		.append("PASSWORD = ?,  LNAME = ?, FNAME= ?, EMAIL = ? ")
		.append(" WHERE USERID = ?");


	PreparedStatement pstmt = con.prepareStatement (sql.toString());

	pstmt.setString(1, userInfo.getPassword());
	pstmt.setString(2, userInfo.getLname());
	pstmt.setString(3, userInfo.getFname());
	pstmt.setString(4, userInfo.getEmail());
	pstmt.setString(5, userid);

       int row = pstmt.executeUpdate ();

	if( row != 0 ) {
	  retval = true;
	}

        if( con.getAutoCommit() == false ) {
          con.commit();
        }
	pstmt.close();

     } catch( Exception ex ) {
	throw new AuthenticationException( ex.toString());
    }
    return retval;
  }
}
We use AuthenticateFactory  to create the authentication module.