5 de abril, 2020

Acceso remoto a base de datos como sistema de login

Futura mejora para Geome7ric

    La motivación era poder autenticar usuarios para el inicio de sesión del programa, a fin de poder ofrecerlo como servicio: mientras se pague el abono mensual los usuarios y contraseñas provistos al cliente no cambiarán y podrán acceder a usar el programa sin problemas, ante falta de pago, se le cambia la contraseña y se inhabilita el programa.

    Para la prueba, Salva (que por cierto es el tester oficial e indiscutido del programa 😛) creó una pequeña base de datos MySQL con una tabla 'usuarios' que contenía los atributos 'user' y 'password', creó el usuario 'userExterno' con todos los privilegios y la levantó en el servidor del Netword Attached Storage (NAS). Además habilitó un puerto para que yo me pueda conectar. Cuando terminó, yo disponía del usuario de la base de datos para conectarme con su correspondiente contraseña, la dirección ip del host y el puerto por el que debía comunicarme, i.e., todo lo que se requiere para establecer una conexión.

    Hice un nuevo proyecto Java Maven en la IDE Netbeans y una clase cuyo propósito era consultar el contenido de la tabla 'usuarios', modificar la pwd de uno de los usuarios y volver a consultar su contenido, para ver los cambios efectuados.

Los imports necesarios

import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.JOptionPane;
import java.sql.Connection;

Métodos

public void establecerParametros()
{
        /*
                Credenciales y direcciones para la conexión
        */
        driver = "com.ibm.db2.jcc.DB2Driver";
        servidor = "direccionServidor";
        baseDatos = "mjRios";
        usuario = "userExterno";
        clave = "passDeUserExterno";
        urlConexion = "jdbc:mysql://" + servidor + "/" + baseDatos;
}

private boolean conectarDB()
{
        /*
                Intentar obtener la conexión a través de DriverManager
                y retornar verdadero en caso positivo y falso caso contrario
        */
         boolean toret=false;
         try
        {
                 conet = DriverManager.getConnection(urlConexion, usuario, clave);
                 toret=true;
                 System.out.println("Conecte a la database "+ baseDatos);
         }
         catch (SQLException ex)
         {
                 JOptionPane.showMessageDialog(this,
                         "Se produjo un error al intentar conectarse a la base de datos en conectarDB.\n" + ex.getMessage(), "Error",
                         JOptionPane.ERROR_MESSAGE);
                 System.out.println("SQLException: " + ex.getMessage());
                 System.out.println("SQLState: " + ex.getSQLState());
                 System.out.println("VendorError: " + ex.getErrorCode());
         }
         return toret;
}

public void ejecutarSelectPrueba()
{
        /*
                Llamada a ejecutar consulta selectSQL y mostrarlo en consola
        */
         System.out.println("---------\nEstado de la tabla Usuarios. \n --------------");
         String selectSQL= "select * from usuarios";
         mostrarContenidoRS(runSelect(selectSQL));
}

public void ejecutarUpdatePrueba()
{
        /*
                Llamada a ejecutar consulta updateSQL
        */
        String nuevaPassword=new String ("\"passJava\"");
        String updateSQL= "update usuarios set password="+nuevaPassword+" where user=\"matias\"";
        runUpdate(updateSQL);
}

public ResultSet runSelect(String sql)
{
        /*
                Ejecutar consulta SELECT de la sentencia pasada por parámetro
                 y retornar el ResultSet que devuelve executeQuery()
        */
         ResultSet toret=null;
         try
        {
                 Statement stat = conet.createStatement();
                 PreparedStatement preparedStmt = conet.prepareStatement(sql);
                 toret = preparedStmt.executeQuery();
         }
         catch (Exception e)
         {
                 e.printStackTrace();
         }
         return toret;
}

public void mostrarContenidoRS(ResultSet rs)
{
        /*
                Mostrar el contenido del Result set recibido por parámetro en la consola
        */
         if (rs!=null)
         {
                 try
                 {
                         while (rs.next())
                         {
                                 System.out.println("user = " + rs.getString("user"));
                                 System.out.println("pass = " + rs.getString("password"));
                         }
                 }
                 catch(Exception ex)
                 {
                         JOptionPane.showMessageDialog(this,
                                 "Se produjo un error al intentar mostrar el contenido del Result Set.\n" + ex.getMessage(), "Error",
                         JOptionPane.ERROR_MESSAGE);
                 }
         }
}

public void runUpdate(String sql)
{
        /*
                Ejecutar UPDATE de la sentencia pasada por parámetro para modificar la base de datos
        */
         try
        {
                 Statement stat = conet.createStatement();
                 PreparedStatement preparedStmt = conet.prepareStatement(sql);
                 preparedStmt.executeUpdate();
         }
         catch (Exception ex)
         {
                 JOptionPane.showMessageDialog(this,
                                 "Se produjo un error al intentar ejecutar el update= "+sql+"\n" + ex.getMessage(), "Error",
                                 JOptionPane.ERROR_MESSAGE);
                 System.out.println("SQLException: " + ex.getMessage());
         }
}

        El resultado de la ejecución fue el siguiente

         Output - Run (pruebaLoca)

         cd C:\Users\mjrca\Documents\NetBeansProjects\LocurasEnLaSalvabase;

         Conecte a la database mjRios
         Estado de la tabla Usuarios.
                 user = matias pass = passmati
                 user = salva pass = passsalva
         Estado de la tabla Usuarios.
                 user = matias pass = passJava
                 user = salva pass = passsalva

        Como se puede apreciar, se cambió el valor "passmati" remotamente del atributo 'pass' por el valor "passJava" correspondiente al user "matias" en la tabla 'usuarios' de la base de datos mjRios. El programa en desarrollo en un futuro podrá validar usuario y contraseña proporcionado al cliente contra la base de datos con un método que evalúe si este está autorizado o no a usar el programa. Es importante aclarar que es muy probable que se reemplace la base de datos MySQL por un sistema más especifico de autenticación, sólo se usó MySQL para hacer la prueba y ver si erea viable la idea de utilizar la NAS de Salva como servidor para proveer servicios remotos.