Usually, in a web application, we will log in by using a username(email id/login name) with a password. Securely we can do the same by using an APIKey as well. Let us see what is an APIKey. The API key is a unique identifier that authenticates requests and if several users are there, their username or email id can be joined with the current date and a secure code meant only for that project by using the md5 mechanism, we can create APIKey and can maintain in a database. Let us see the ways of creating APIKey and inserting it into the database.
Example Project
MySQL table structure:
-- Sample table named users is available CREATE TABLE `users` ( `userId` int(11) NOT NULL AUTO_INCREMENT, `loginId` varchar(20) DEFAULT NULL, apiKey varchar(255) DEFAULT NULL, PRIMARY KEY (`userId`) ); -- insert 2 records insert into users (loginId) values ('geeka@gmail.com'); insert into users (loginId) values ('geekb@gmail.com');
Now let us see the sample java program for the creation of an API key and updating into the ‘users’ (MySQL) table
Java
import static java.nio.charset.StandardCharsets.UTF_8; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.sql.*; import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class CreateAndUpdateAPIKey { Connection conn; // To generate MD5 hashvalue public String generateMD5Hashvalue(String userName) { LocalDate dateObj = LocalDate.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMdd" ); String date = dateObj.format(formatter); MessageDigest md; try { md = MessageDigest.getInstance( "MD5" ); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } String secretPhase = "geeks" ; // exclusively to set for geeks System.out.println( "Current Date : " + date); System.out.println( "Login Id : " + userName); System.out.println( "Secret Phase : " + secretPhase); // By using the current date, userName(emailId) and // the secretPhase , it is generated byte [] hashResult = md.digest((date + userName + secretPhase) .getBytes(UTF_8)); // convert the value to hex String password = bytesToHex(hashResult); System.out.println( "Generated password.." + password); return password; } private String bytesToHex( byte [] bytes) { StringBuilder sb = new StringBuilder(); for ( byte b : bytes) { sb.append(String.format( "%02x" , b)); } return sb.toString(); } public static void main(String[] args) { // let us assume there is a table 'users' available // By passing as an argument, we can have that for // any table new CreateAndUpdateAPIKey( "users" ); } public CreateAndUpdateAPIKey(String tableName) { try { // connecting to mySQL Class.forName( "com.mysql.jdbc.Driver" ) .newInstance(); String url conn = DriverManager.getConnection(url, "root" , "admin" ); doSelectAndUpdate(tableName); conn.close(); } catch (ClassNotFoundException ex) { System.err.println(ex.getMessage()); } catch (IllegalAccessException ex) { System.err.println(ex.getMessage()); } catch (InstantiationException ex) { System.err.println(ex.getMessage()); } catch (SQLException ex) { System.err.println(ex.getMessage()); } } private void doSelectAndUpdate(String tableName) { doSelect(tableName); } private void doSelect(String tableName) { String query = null , userName = null ; // Query the respective table. If multiple tables // are possible, then we should have separate if or // switch statements query = "SELECT * FROM users" ; try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(query); while (rs.next()) { // loginId is the unique column to identify // the user userName = rs.getString( "loginId" ); // Get the MD5 value and get as password String password = generateMD5Hashvalue(userName); // update the password doUpdate(password, userName, tableName); System.out.println(userName + ":" + password); } } catch (SQLException ex) { System.err.println(ex.getMessage()); } } private void doUpdate(String apiKey, String userName, String tableName) { System.out.print( "\n[Performing UPDATE] ... " ); try { Statement st = conn.createStatement(); // Use the generated password for apiKey String sqlUpdate = null ; sqlUpdate = "UPDATE users " + "SET apikey = ? " + "WHERE loginId = ?" ; PreparedStatement pstmt = conn.prepareStatement(sqlUpdate); pstmt.setString( 1 , apiKey); pstmt.setString( 2 , userName); int rowAffected = pstmt.executeUpdate(); System.out.println(String.format( "Row affected %d" , rowAffected)); } catch (SQLException ex) { System.err.println(ex.getMessage()); } } } |
On execution of the above program, we can see below the output We can see the API key updation below in MySQL as well.
Now let us try to login into the sample by using login id and apiKey. Main important thing is apiKey will be changed on daily basis because of the date. In order to make this happen. this java code needs to be placed as a ‘CRON’ job in Linux servers. We can have a sample JSP page where we should have the provision to key in loginId and apiKey.
HTML
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html> < html > < head > < meta charset = "ISO-8859-1" > < title >Login Form With APIKey</ title > </ head > < body > < div align = "center" > < h1 >Login Form - API KEY</ h1 > < form action="<%=request.getContextPath()%>/login" method="post"> < table style = "with: 100%" > < tr > < td >Login</ td > < td >< input type = "text" name = "loginId" /></ td > </ tr > < tr > < td >APIKEY</ td > < td >< input type = "password" name = "apiKey" /></ td > </ tr > </ table > < input type = "submit" value = "Submit" /> </ form > </ div > </ body > </ html > |
Once the information is received it will be stored in the bean and get validated. Let’s see the validation one.
LoginWithAPIKeyDao.java
Java
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import net.gfg.login.bean.LoginBean; public class LoginWithAPIKeyDao { public boolean validate(LoginBean loginBean) throws ClassNotFoundException { boolean status = false ; Class.forName( "com.mysql.jdbc.Driver" ); try { Connection connection = DriverManager.getConnection( "root" , "admin" ); // We have to query the users table with the // passed information PreparedStatement preparedStatement = connection.prepareStatement( "select * from users where loginId = ? and apiKey = ?" ); preparedStatement.setString( 1 , loginBean.getLoginId()); preparedStatement.setString( 2 , loginBean.getApiKey()); ResultSet rs = preparedStatement.executeQuery(); // For the given query, if there is a record while (rs.next()) { status = true ; // make the status to true } } catch (SQLException e) { // process sql exception displaySQLException(e); } return status; } private void displaySQLException(SQLException ex) { // for (Throwable e : ex) { if (ex instanceof SQLException) { ex.printStackTrace(System.err); System.err.println( "SQLState: " + ((SQLException)ex).getSQLState()); System.err.println( "Error Code: " + ((SQLException)ex).getErrorCode()); System.err.println( "Message: " + ex.getMessage()); Throwable t = ex.getCause(); while (t != null ) { System.out.println( "Cause: " + t); t = t.getCause(); } } // } } } |
and then it will get redirected to the success page or further mechanism
Conclusion
In this article, we have seen how to generate APIKey by using the MD5 mechanism and using the loginId/apiKey how to login into an application.