Создайте простое веб-приложение для входа в систему с зашифрованным паролем на Java

Опубликовано: 9 Августа, 2022

Безопасность — важная концепция в любом веб-приложении. Нам необходимо, чтобы пароли хранились в зашифрованном виде, т.е. пароли не были легко доступны хакерам или неавторизованным пользователям. Давайте рассмотрим небольшое демонстрационное приложение в этой статье, использующее технологии MySQL, Java, Servlet и JSP.

Пошаговая реализация

Требуемый скрипт MySQL

-- Here GEEKSFORGEEKS is the db name
create table GEEKSFORGEEKS.login_key (
  keyValue varchar(255)
  );

В это keyValue должно быть вставлено случайное значение. Это значение должно быть вставлено один раз, и с его помощью мы можем поиграть с шифрованием и дешифрованием. Код для вставки случайного значения.

Java




public static final String AES = "AES";
// This method generates a random key and stores in
// login_key table In the full program, let us see whole
// connection details
private void oneTimeKeyGeneration()
{
    try {
        KeyGenerator keyGen = KeyGenerator.getInstance(AES);
        keyGen.init(128);
        SecretKey sk = keyGen.generateKey();
        String key = byteArrayToHexString(sk.getEncoded());
        System.out.println("key:" + key);
        getAndStoreLoginKey(key);
    }
    catch (Exception ex) {
        System.out.println(ex.getMessage());
    }
}
private static String byteArrayToHexString(byte[] b)
{
    StringBuffer sb = new StringBuffer(b.length * 2);
    for (int i = 0; i < b.length; i++) {
        int v = b[i] & 0xff;
        if (v < 16) {
            sb.append("0");
        }
        sb.append(Integer.toHexString(v));
    }
    return sb.toString().toUpperCase();
}
 
private void getAndStoreLoginKey(String key)
{
 
    try {
        Class.forName("com.mysql.cj.jdbc.Driver")
            .newInstance();
        // Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection(
            "root", "admin");
 
        String sql
            = "INSERT INTO login_key(keyValue) VALUES(?)";
 
        PreparedStatement pst = conn.prepareStatement(sql);
 
        pst.setString(1, key);
        pst.executeUpdate();
    }
    catch (ClassNotFoundException ex) {
        Logger
            .getLogger(
                EncryptAndStorePassword.class.getName())
            .log(Level.SEVERE, null, ex);
    }
    catch (SQLException ex) {
        System.out.println("Exception.." + ex.getMessage());
    }
    catch (InstantiationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Когда вставляется случайный ключ, мы можем получать значения, как показано ниже.

Давайте создадим таблицу «GEEKPORTALLOGIN» и создадим в ней 2 записи.

CREATE TABLE GEEKSFORGEEKS.GEEKPORTALLOGIN (id INT NOT NULL,
   loginName VARCHAR(20) default NULL,
   password VARCHAR(45) default NULL,
   PRIMARY KEY (id)
);
INSERT INTO GEEKSFORGEEKS.GEEKPORTALLOGIN VALUES(1,"GEEKA","GEEKA");
INSERT INTO GEEKSFORGEEKS.GEEKPORTALLOGIN VALUES(2,"GEEKB","GEEKB");

Используя ключ, указанный в «Образ ключа», пароль можно зашифровать с помощью приведенного ниже кода.

Java




import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
 
public class EncryptAndStorePassword {
    Connection conn = null;
    public static final String AES = "AES";
    String key = null;
    public Connection getConnection()
    {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver")
                .newInstance();
            conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/geeksforgeeks?useSSL=false",
                "root", "admin");
 
            Statement st;
 
            st = conn.createStatement();
            ResultSet rs = st.executeQuery(
                "select * from login_key");
            // Get the key value from login_key
            while (rs.next()) {
                key = rs.getString("keyValue");
            }
            System.out.println("key=" + key);
        }
        catch (ClassNotFoundException ex) {
            Logger
                .getLogger(
                    EncryptAndStorePassword.class.getName())
                .log(Level.SEVERE, null, ex);
        }
        catch (SQLException ex) {
            System.out.println("Exception.."
                               + ex.getMessage());
        }
        catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return conn;
    }
    private void closeConnection()
    {
        try {
            conn.close();
            conn = null;
        }
        catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    // Utility method taking input as byte array and giving
    // String as output
    private static String byteArrayToHexString(byte[] b)
    {
        StringBuffer sb = new StringBuffer(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            int v = b[i] & 0xff;
            if (v < 16) {
                sb.append("0");
            }
            sb.append(Integer.toHexString(v));
        }
        return sb.toString().toUpperCase();
    }
    // Utility method taking input as String and giving byte
    // array as output
    private static byte[] hexStringToByteArray(String s)
    {
        byte[] b = new byte[s.length() / 2];
        for (int i = 0; i < b.length; i++) {
            int index = i * 2;
            int v = Integer.parseInt(
                s.substring(index, index + 2), 16);
            b[i] = (byte)v;
        }
        return b;
    }
 
    public EncryptAndStorePassword(String tableName)
    {
        getConnection();
        // oneTimeKeyGeneration();//This has to be done only
        // one time. Based on the key, password are getting
        // encrypted and using this key only decrypt will
        // happen and check for username and password
        // combination
        doSelectAndUpdate(tableName);
        closeConnection();
    }
 
    private void doSelectAndUpdate(String tableName)
    {
        doSelect("GEEKPORTALLOGIN");
        // Passing table name will be a good approach as it
        // can do for any table. Just change table name alone
    }
    // This is the one time approach of storing key value in
    // login_key
    private void getAndStoreLoginKey(String key)
    {
 
        try {
 
            String sql
                = "INSERT INTO login_key(keyValue) VALUES(?)";
 
            PreparedStatement pst
                = conn.prepareStatement(sql);
 
            pst.setString(1, key);
            pst.executeUpdate();
        }
        catch (SQLException ex) {
            System.out.println("SQLException.."
                               + ex.getMessage());
        }
    }
    // This is the one time approach of storing key value in
    // login_key
    private void oneTimeKeyGeneration()
    {
        try {
            KeyGenerator keyGen
                = KeyGenerator.getInstance(AES);
            keyGen.init(128);
            SecretKey sk = keyGen.generateKey();
            String key
                = byteArrayToHexString(sk.getEncoded());
            System.out.println("key:" + key);
            getAndStoreLoginKey(key);
        }
        catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
    // Get the details from GEEKPORTALLOGIN and update
    // encrypted password
    private void doSelect(String tableName)
    {
        Statement st;
        String query = null, password = null,
               userName = null;
        query = "SELECT * FROM GEEKPORTALLOGIN";
 
        try {
            st = conn.createStatement();
            ResultSet rs = st.executeQuery(query);
            while (rs.next()) {
                userName = rs.getString("loginName");
 
                password = rs.getString("password");
                byte[] passwordByte
                    = hexStringToByteArray(key);
                System.out.println("keyValue.." + key);
                SecretKeySpec sks = new SecretKeySpec(
                    passwordByte,
                    EncryptAndStorePassword.AES);
                Cipher cipher = Cipher.getInstance(
                    EncryptAndStorePassword.AES);
                cipher.init(Cipher.ENCRYPT_MODE, sks,
                            cipher.getParameters());
                byte[] encrypted
                    = cipher.doFinal(password.getBytes());
                String encryptedpwd
                    = byteArrayToHexString(encrypted);
                // System.out.println("****************
                // Encrypted Password  ****************");
                System.out.println(encryptedpwd);
                // System.out.println("****************
                // Encrypted Password  ****************");
                doUpdate(encryptedpwd, userName,
                         "GEEKPORTALLOGIN");
            }
        }
        catch (SQLException ex) {
            Logger
                .getLogger(
                    EncryptAndStorePassword.class.getName())
                .log(Level.SEVERE, null, ex);
        }
        catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }
 
    // Updating encrypted password for the users
    private void doUpdate(String password, String userName,
                          String tableName)
    {
        System.out.print(" [Performing UPDATE] ... ");
        try {
            Statement st = conn.createStatement();
            String sqlUpdate = null;
 
            sqlUpdate = "UPDATE GEEKPORTALLOGIN "
                        + "SET password = ? "
                        + "WHERE loginName = ?";
 
            PreparedStatement pstmt
                = conn.prepareStatement(sqlUpdate);
 
            pstmt.setString(1, password);
            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());
        }
    }
 
    public static void main(String args[])
        throws NoSuchAlgorithmException
    {
        EncryptAndStorePassword encryptAndStorePassword
            = null;
        // Open a connection