SISTEMAS COMPUTACIONALESANALISIS Y DISEÑO III DAVID UC SALAS DOCUMENTAL PARA EL DESARROLLO DE UN SISTEMA DE LECTURA DE HUELLA DIGITAL DEYADIRA MORALES MADRID 15 DE JUNIO DEL 2012 DESARROLLO DE UN SISTEMA DE HUELLA DIGITAL CON JAVA Y MYSQL Biometría. Las huellas dactilares humanas La biometría es una tecnología de seguridad basada en el reconocimiento de una característica física e intransferible de las personas, como por ejemplo, la huella digital. Aunque hay muchos otros aspectos que podemos “medir” de una persona y que lo hacen único; los más utilizados hoy en día son: huella, iris, voz, retina, cara, palma de la mano y firma. Una huella dactilar o huella digital es la impresión visible o moldeada que produce el contacto de las crestas papilares. El Patrón De la Huella digital Las huellas digitales son el resultado de los surcos y líneas que se encuentran en la mano de cada persona. En la yema de los dedos estos surcos forman tres distintos patrones: Curva, espiral y arco. En el patrón de “Curva” hay dos puntos focales: el nucleo , o el centro del patrón, y el delta. El delta es el área del patrón donde hay una triangulación o división de las líneas. Al imprimirse las huellas digitales, el delta y el área entre el delta y el núcleo deben imprimirse completamente. Un patrón de Espiral tendrá dos o más deltas. Para un patrón de Espiral, todos los deltas y las áreas entre ellos deben ser impresos. El patrón de arco no tiene ningún delta o núcleo; pero, también, debe ser impreso completamente de modo que sus características individuales puedan ser fácilmente distinguidas. ¿Cuál es el proceso para tomar una huella digital? Un lector óptico funciona con un dispositivo CCD (Charged Coupled Device), como el usado en las cámaras digitales, que tienen un array de diodos sensibles a la luz que generan una señal eléctrica en respuesta a fotones de luz. Cada diodo graba un pixel, un pequeño punto que representa la luz que le es reflejada. Cuando terminamos de pasar el dedo por el lector, se recuperan todos los pixeles situándolos en su posición correcta y formando así la imagen. En el lector de tipo conductivo hay una placas conductoras capacitivas diminutas, que gracias a las crestas de nuestro dedo, uniremos, o en los valles, mantendremos en circuito abierto.Al variar la distancia entre las placas capacitoras (moviendo el dedo más cerca o más lejos de las placas conductoras), se cambia la capacitancia (o habilidad para almacenar una carga) total del capacitor. Gracias a esta cualidad, el capacitor en una celda bajo una cresta tendrá una capacitancia más grande que el capacitor en una celda bajo un valle. Ya que la distancia al dedo altera la capacitancia, la cresta de un dedo resultará en una salida de voltaje diferente a la del valle de un dedo. Una vez hayamos pasado el dedo, el sensor reconstruirá la imagen de nuestra huella dactilar. Una imagen vale más que mil palabras de explicación: Para el desarrollo del proyecto, se utiliza el IDE para programar en Java de Oracle, llamado NetBeans 7.1 PASOS PARA INSTALAR NETBEANS 1. Descargar NetBeans http://www.buzzdock.com/search?query=descargar+netbeans+7.0+gratis 2. Abre la carpeta en la que lo guardaste. 3. Dar doble click en el programa netbeans-7.1.2 4. Dar click en siguiente 5. Finalizar 6. Inicio, Todos los programas, NetBeans IDE 7. Doble click en NetBeans y listo para utilizar Fingerprint SDK es un software development kit (SDK) que permite desarrollar una gran variedad de aplicaciones para ser utilizada en el reconocimiento de huellas dactilares. Se debe hacer la Instalación del API de programación de Griaule: Fingerprint_SDK_Java_2007_Installer.jar, para comenzar la instalación se realiza lo siguiente: 1. Doble clic sobre el archivo, aparecerá una ventana que nos pide elegir el idioma, selecciona el que desees. 2. Posteriormente aparece la pantalla de bienvenida y si se da clic en Siguiente aparecen los términos de la licencia, los cuales se debe aceptar para poder continuar. 3. Una vez hecho lo anterior se selecciona la ruta donde se instalará, aquí se dejan los valores por defecto. 4. Después de la ruta de instalación se debe elegir los elementos que se instalarán, de igual manera se deja todo marcado y se da clic en Siguiente. 5. Posteriormente se instalan los elementos seleccionados, dejando al final la instalación del controlador. NOTA: Es de suma importancia tomar en cuenta que antes de la instalación del lector de huella digital, este se debe de tener desconectado y de preferencia desinstalar el software y controladores que venían con él de fábrica para evitar conflictos durante la actual instalación. 6. Ahora aparece una pantalla para seleccionar el idioma de la instalación del controlador, de igual manera se elige el que más convenga. 7. Después aparece la pantalla de bienvenida... aquí se da clic en Siguiente o Next. 8. Se aceptan los términos de la licencia y se da clic en Siguiente un par de veces. 9. Posteriormente presionamos el botón de Instalar o Install para que se realice la instalación de los controladores del lector. 10. Al terminar el proceso se da clic en el botón de Siguiente y posteriormente en Finalizar para terminar la instalación del controlador. 11. Una vez hecho esto se sigue con la pantalla del proceso de instalación general... ... y se da clic en Siguiente o Next. 12. Al final se da clic en el botón Done para culminar. De igual forma se deben instalar los Drivers del lector de huella en este caso se utiliza el siguiente: Griaule_FingerCap_USB_Driver_2_1_Installer Pasos de instalación: 1. Doble click en el icono del Driver 2. Click en ok 3. Next 4. Next ,Click en Install. 5. Finalizar NOTA: Este Driver se utiliza solo para los equipos que tengan sistema operativo de 32 bits, en caso de que su equipo sea de 64 bits puedes descargarlo de la siguiente página: http://www.griaulebiometrics.com/?gclid=CI7gtdixzLACFQFeTAodanEfWA En seguida se muestra el código que se debe capturar en NetBeans para poder realizar el sistema de lector de huella. Como pueden observar, nuestro proyecto se llama LectorHuellas y consta de tres clases, y cada una de éstas (las clases) tiene su respectiva función dentro del proyecto: Clase Interfaz Esta clase contiene el archivo PantallaPrincipal.java y es quien se encarga de diseñar la interfaz principal de nuestro sistema de autenticación por huella digital. Diseño de la pantalla principal de nuestro sistema El contenido del archivo PantallaPrincipal.java es el siguiente: /** * @package: interfaz * @class: PantallaPrincipal * @author: Ricardo Rosero * @version: 1.0 */ package interfaz; /** * @librerias importadas * @author: Ricardo Rosero */ import com.griaule.grfingerjava.GrFingerJavaException; import java.awt.Graphics; import java.awt.Insets; import java.awt.image.BufferedImage; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.border.BevelBorder; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import procedimientos.Util; public class PantallaPrincipal extends javax.swing.JFrame { /** * @atributos * @author: Ricardo Rosero * @access: private */ //objecto usado para realizar todas las operaciones relacionadas al Fingerprint-SDK private Util procedimientosSDK; //Panel para mostrar la huella digital private JPanel fingerprintViewPanel = null; //Imagen de la huella actual private BufferedImage fingerprintImage = null; /** * @function: PantallaPrincipal * @author: Ricardo Rosero * @access: public * @return */ public PantallaPrincipal() { inicializar(); initComponents(); procedimientosSDK.inicializarCaptura(); setLocationRelativeTo(null); setVisible(true); } /** * @function: inicializar * @author: Ricardo Rosero * @access: public * @return */ public void inicializar() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { System.err.println(―No se pudo aplicar el estilo visual‖); } //Crea una instancia de Util this.procedimientosSDK = new Util(this); } /** * @function: crearPanelHuella * @author: Ricardo Rosero * @access: private * @return */ private JComponent crearPanelHuella() { //Crea un panel nuevo para mostrar la huella fingerprintViewPanel = new JPanel(){ //Se sobreescribe el método paintComponent para habilitar la muestra de la imagen de la huella public void paintComponent(Graphics g) { super.paintComponent(g); //Si hay una imagen para ser mostrada if (fingerprintImage!=null) { //Calcula el tamaño y posición de la imagen para ser pintada el tamaño es ajustado para que ocupe todo el tamaño del panel Insets insets = getInsets(); int transX = insets.left; int transY = insets.top; int width = getWidth() – getInsets().right – getInsets().left; int height = getHeight() – getInsets().bottom – getInsets().top; //Se dibuja la imagen g.drawImage(fingerprintImage, transX, transY, width, height, null); } } }; //Se agrega un border alrededor del panel fingerprintViewPanel.setBorder(new CompoundBorder ( new EmptyBorder (2,2,2,2), new BevelBorder(BevelBorder.LOWERED))); fingerprintViewPanel.setToolTipText(―Imagen de la última huella capturada.‖); if(fingerprintViewPanel==null){ System.exit(1); return null; } else{ return fingerprintViewPanel; } } /** * @function: showImage * @author: Ricardo Rosero * @access: public * @return */ public void showImage(BufferedImage image) { //Utiliza el imageProducer para crear una imagen de la huella digital fingerprintImage = image; //Se dibuja la nueva imagen repaint(); } /** * @function: initComponents * @author: Ricardo Rosero * @access: private * @return */ @SuppressWarnings(―unchecked‖) // <editor-fold defaultstate=‖collapsed‖ desc=‖Generated Code‖> private void initComponents() { jPanel2 = new javax.swing.JPanel(); btnIdentificar = new javax.swing.JButton(); btnGuardar = new javax.swing.JButton(); btnSalir = new javax.swing.JButton(); PanelContenedor = new javax.swing.JPanel(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setResizable(false); addWindowListener(new java.awt.event.WindowAdapter() { public void windowActivated(java.awt.event.WindowEvent evt) { formWindowActivated(evt); } public void windowClosing(java.awt.event.WindowEvent evt) { formWindowClosing(evt); } }); jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED), ―Acciones‖, javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION)); btnIdentificar.setText(―Identificar‖); btnIdentificar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnIdentificarActionPerformed(evt); } }); btnGuardar.setText(―Guardar‖); btnGuardar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnGuardarActionPerformed(evt); } }); btnSalir.setText(―Salir‖); btnSalir.setAlignmentY(0.0F); btnSalir.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { btnSalirActionPerformed(evt); } }); javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEA DING) .addGroup(jPanel2Layout.createSequentialGroup() .addComponent(btnIdentificar, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(btnGuardar, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(btnSalir, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(100, 100, 100)))) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel2Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BAS ELINE) .addComponent(btnGuardar, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(btnIdentificar, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(btnSalir, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); PanelContenedor.setBorder(javax.swing.BorderFactory.createTitledBorder(null, ―Huella Digital‖, javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION)); PanelContenedor.setLayout(new java.awt.BorderLayout()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(PanelContenedor, javax.swing.GroupLayout.PREFERRED_SIZE, 364, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(PanelContenedor, javax.swing.GroupLayout.PREFERRED_SIZE, 353, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); PanelContenedor.getAccessibleContext().setAccessibleParent(jPanel2); pack(); }// </editor-fold> /** * @function: btnGuardarActionPerformed * @author: Ricardo Rosero * @access: private * @return */ private void btnGuardarActionPerformed(java.awt.event.ActionEvent evt) { try { //procedimientosSDK.guardarHuella(); //procedimientosSDK.guardarHuellaBackup(); procedimientosSDK.guardar(); } catch (GrFingerJavaException ex) { Logger.getLogger(PantallaPrincipal.class.getName()).log(Level.SEVERE, null, ex); } } /** * @function: btnSalirActionPerformed * @author: Ricardo Rosero * @access: private * @return */ private void btnSalirActionPerformed(java.awt.event.ActionEvent evt) { dispose(); } /** * @function: formWindowActivated * @author: Ricardo Rosero * @access: private * @return */ private void formWindowActivated(java.awt.event.WindowEvent evt) { this.PanelContenedor.add(this.crearPanelHuella()); } /** * @function: formWindowClosing * @author: Ricardo Rosero * @access: private * @return */ private void formWindowClosing(java.awt.event.WindowEvent evt) { } /** * @function: btnIdentificarActionPerformed * @author: Ricardo Rosero * @access: private * @return */ private void btnIdentificarActionPerformed(java.awt.event.ActionEvent evt) { try { procedimientosSDK.identificarPersona(); } catch (GrFingerJavaException ex) { Logger.getLogger(PantallaPrincipal.class.getName()).log(Level.SEVERE, null, ex); } } /** * @atributos * @author: Ricardo Rosero * @access: private */ // Variables declaration – do not modify private javax.swing.JPanel PanelContenedor; private javax.swing.JButton btnGuardar; private javax.swing.JButton btnIdentificar; private javax.swing.JButton btnSalir; private javax.swing.JPanel jPanel2; // End of variables declaration } Clase Procedimientos Esta clase contiene el archivo Util.java y su estructura es la siguiente: /** * @package: procedimientos * @class: Util * @author: Ricardo Rosero * @version: 1.0 */ package procedimientos; /** * @librerias importadas * @author: Ricardo Rosero */ import com.griaule.grfingerjava.FingerprintImage; import com.griaule.grfingerjava.GrFingerJava; import com.griaule.grfingerjava.GrFingerJavaException; import com.griaule.grfingerjava.IFingerEventListener; import com.griaule.grfingerjava.IImageEventListener; import com.griaule.grfingerjava.IStatusEventListener; import com.griaule.grfingerjava.MatchingContext; import com.griaule.grfingerjava.Template; import com.mysql.jdbc.Blob; import interfaz.PantallaPrincipal; import java.io.ByteArrayInputStream; import java.io.File; 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 javax.swing.JOptionPane; import java.io.InputStream; public class Util implements IStatusEventListener, IImageEventListener, IFingerEventListener{ /** * @atributos * @author: Ricardo Rosero * @access: public y private */ /**Contexto utilizado para la captura, extracción y coincidencia de huellas digitales */ private MatchingContext fingerprintSDK; /**Interfaz de usuario donde se muestra la imagena de la huella*/ private PantallaPrincipal ui; /** Indica si la plantilla o template debe ser extraída automáticamente*/ private boolean autoExtract = true; /** Arreglo que contiene localmente los datos de las huellas capturadas */ private ByteArrayInputStream fingerprintData, fingerprintData2; /**Arreglo que contiene la longitud del dato de la huella*/ private int fingerprintDataLength, fingerprintDataLenght2; /** La imagen de la última huella digital capturada. */ private FingerprintImage fingerprint, fingerprint2; /** La plantilla de la última imagen de huella capturada */ public com.griaule.grfingerjava.Template template, template2; /** La conexion con la base de datos */ private Connection dbConnection; /** Consultas SQL */ private PreparedStatement guardarStmt, guardar2; private PreparedStatement identificarStmt; private PreparedStatement verificarStmt; private PreparedStatement verificarDatosUsuario; private PreparedStatement verificaCedulaUsuario; private PreparedStatement verificaCedulaHuellaUsuario; private PreparedStatement verficaHuellaUsuario; /** * @function: Util * @author: Ricardo Rosero * @access: public * @return */ public Util(PantallaPrincipal ui) { this.ui = ui; //Inicializa la conexión a la BD. initDB(); } /** * @function: inicializarCaptura * @author: Ricardo Rosero * @access: public * @return: */ public void inicializarCaptura() { try { fingerprintSDK = new MatchingContext(); //Inicializa la captura de huella digital. GrFingerJava.initializeCapture(this); } catch (Exception e) { //Si ocurre un error durante la inicialización se indica con un mensaje y se cierra la aplicación. e.printStackTrace(); System.exit(1); } } /** * @function: initDB * @author: Ricardo Rosero * @access: private * @return */ private void initDB() { try { //Carga el driver ODBC Class.forName(―com.mysql.jdbc.Driver‖); //Se conecta a la bd dbConnection = DriverManager.getConnection(―jdbc:mysql://localhost:3306/huellas‖,‖root‖, ―rrosero1980″); Statement stm = dbConnection.createStatement(); //Prepara las consultas/sentencias que se utilizarán guardarStmt = dbConnection.prepareStatement(―INSERT INTO huella(identificacion_usuario, nombres_usuario, huella1_usuario, huella2_usuario) values(?,?,?,‖)‖); guardar2 = dbConnection.prepareStatement(―update huella set huella2_usuario=? where (identificacion_usuario=?)‖); identificarStmt = dbConnection.prepareStatement(―SELECT nombres_usuario, huella1_usuario, huella2_usuario FROM huella‖); verificarStmt = dbConnection.prepareStatement(―SELECT huella1 FROM huella WHERE nombres_usuario=?‖); verificarDatosUsuario = dbConnection.prepareStatement(―select * from huella where identificacion_usuario=?‖); verificaCedulaUsuario = dbConnection.prepareStatement(―select identificacion_usuario from huella where (identificacion_usuario=?)‖); verificaCedulaHuellaUsuario = dbConnection.prepareStatement(―select identificacion_usuario, huella1_usuario from huella where (identificacion_usuario=?)‖); verficaHuellaUsuario = dbConnection.prepareStatement(―selec * from huella where (huella1_usuario=?)‖); } catch (Exception e) { e.printStackTrace(); } } /** * @function: destroyDB * @author: Ricardo Rosero * @access: private * @return */ private void destroyDB() { try { //Se cierran todas las sentencias guardarStmt.close(); identificarStmt.close(); //Cierra la conexión a la base dbConnection.close(); } catch (Exception e) { e.printStackTrace(); } } /** * @function: setFingerprintSDKNativeDirectory * @author: Ricardo Rosero * @access: public * @return */ public static void setFingerprintSDKNativeDirectory(String directorio) { File directory = new File(directorio); try { GrFingerJava.setNativeLibrariesDirectory(directory); GrFingerJava.setLicenseDirectory(directory); } catch (GrFingerJavaException e) { e.printStackTrace(); } } /** * @function: onSensorPlug * @author: Ricardo Rosero * @access: public * @return */ public void onSensorPlug(String idSensor) { try { //Comienza la captura con el lector conectado. GrFingerJava.startCapture(idSensor, this, this); } catch (GrFingerJavaException e) { //Indica si ha ocurrido un error con el lector. e.printStackTrace(); } } /** * @function: onSensorUnPlug * @author: Ricardo Rosero * @access: public * @return */ public void onSensorUnplug(String idSensor) { try { GrFingerJava.stopCapture(idSensor); } catch (GrFingerJavaException e) { //Indica si ha ocurrido un error con el lector. e.printStackTrace(); } } /** * @function: onImageAcquired * @author: Ricardo Rosero * @access: public * @return */ public void onImageAcquired(String idSensor, FingerprintImage huellaDigital) { //Almacena la imagen de la huella this.fingerprint=huellaDigital; //Muestra la imagen obtenida ui.showImage(huellaDigital); //Muestra la plantilla en la imagen actual extract(); } /** * @function: extrac * @author: Ricardo Rosero * @access: public * @return */ public void extract() { try { //Extracts a template from the current fingerprint image. template = fingerprintSDK.extract(fingerprint); //display minutiae/segments/directions into image ui.showImage(GrFingerJava.getBiometricImage(template,fingerprint)); } catch (GrFingerJavaException e) { e.printStackTrace(); } } /** * @function: guardar * @author: Ricardo Rosero * @access: public * @return * @throws: GrFingerJavaException */ public void guardar() throws GrFingerJavaException{ fingerprintData = new ByteArrayInputStream(template.getData()); fingerprintDataLength = template.getData().length; String cedula = JOptionPane.showInputDialog(―No. Identificacion:‖); boolean coinciden = false; try{ verificaCedulaHuellaUsuario.setInt(1, Integer.parseInt(cedula)); ResultSet rs = verificaCedulaHuellaUsuario.executeQuery(); //ResultSet rs2 = verficaHuellaUsuario.executeQuery(); //Si se encuentra el nombre en la base de datos if(rs.next()){ //Lee la plantilla de la base de datos byte templateBuffer[] = rs.getBytes(2); //.getBytes(2); //Crea una nueva plantilla Template referenceTemplate = new Template(templateBuffer); //compara las plantilas (actual vs bd) coinciden = fingerprintSDK.verify(template,referenceTemplate); if(coinciden){ JOptionPane.showMessageDialog(null, ―La huella ya existe, coloque un dedo diferente‖); } else{ guardar2.setBinaryStream(1, fingerprintData, fingerprintDataLength); guardar2.setInt(2, Integer.parseInt(cedula)); guardar2.execute(); JOptionPane.showMessageDialog(null, ―Ha guarado la huella de backup‖); } } else if(!rs.next()){ String nombre = JOptionPane.showInputDialog(―Nombre y Apellido:‖); guardarStmt.setInt(1,Integer.parseInt(cedula)); guardarStmt.setString(2,nombre); guardarStmt.setBinaryStream(3, fingerprintData, fingerprintDataLength); guardarStmt.execute(); JOptionPane.showMessageDialog(null, ―La huella ha sido guardada con exito‖); } } catch(SQLException sqlEx){ sqlEx.printStackTrace(); System.out.println(―Se produjo el siguiente error: ―+sqlEx.getMessage()); } } /** * @function: onFingerDown * @author: Ricardo Rosero * @access: public * @return */ public void onFingerDown(String idSensor) { } /** * @function: onFingerUp * @author: Ricardo Rosero * @access: public * @return */ public void onFingerUp(String arg0) { } /** * @function: onFingerUp * @author: Ricardo Rosero * @access: public * @return * @throws: GrFingerJavaException */ public void identificarPersona() throws GrFingerJavaException{ try{ //Obtiene todas las huellas de la bd ResultSet rsIdentificar = identificarStmt.executeQuery(); //Si se encuentra el nombre en la base de datos while(rsIdentificar.next()){ byte templateBuffer[] = rsIdentificar.getBytes(―huella1_usuario‖); Template referenceTemplate = new Template(templateBuffer); if(referenceTemplate!=null){ //Lee la plantilla de la base de datos boolean coinciden = fingerprintSDK.verify(template,referenceTemplate); //Si encuentra correspondencia dibuja el mapa e indica el nombre de la persona que coincidió. if (coinciden){ JOptionPane.showMessageDialog(null, ―Bienvenido ―+rsIdentificar.getString(―nombres_usuario‖)); return; } } } //Si no encuentra alguna huella que coincida lo indica con un mensaje JOptionPane.showMessageDialog(null, ―No existe ningún registro que coincida con la huella.‖); } catch (SQLException e) { System.out.println(―Se produjo el siguiente error: ―+e.getMessage()); e.printStackTrace(); } catch(GrFingerJavaException gr){ System.out.println(―Error con el scanner: ―+gr.getMessage()); gr.printStackTrace(); } } } Cabe recordar que esta clase es la más importante de todas, debido a que en esta clase procedemos a conectar nuestro sistema de autenticacion con el motor de bases de datos mySQL. Clase LectorHuella Esta clase es la más sencilla de todas, y contiene el archivo Main.java , la función de esta clase es simple, se encarga de ejecutar nuestro programa, y su estructura es la siguiente: /** * @package: lectorhuellas * @class: Main * @author: Ricardo Rosero * @version: 1.0 */ package lectorhuellas; /** * @librerias importadas * @author: Ricardo Rosero */ import interfaz.PantallaPrincipal; import java.io.File; import procedimientos.Util; public class Main { /** * @function: main * @author: Ricardo Rosero * @access: public * @param: args argumentos de la funcion * @return */ public static void main(String[] args) { String grFingerNativeDirectory = new File(―.‖).getAbsolutePath(); Util.setFingerprintSDKNativeDirectory(grFingerNativeDirectory); PantallaPrincipal p = new PantallaPrincipal(); } } Como pueden observar en cada una de las clases importamos la librería com.griaule.grfingerjava.*; , este paquete es pago, y hace parte del FingerprintSDK2009 de la empresa Griaule Biometrics. Actualmente es el mejor SDK para la compilación de sistemas de autenticacion basados en huella digital, este paquete tiene la capacidad de comparar 35 mil huellas por segundo. La estructura de nuestra base de datos en MySQL es la siguiente: – ——————————————————– – Host: 127.0.0.1 – Server version: 5.1.36-community – MySQL Community Server (GPL) – Server OS: Win32 – HeidiSQL version: 7.0.0.4053 – Date/time: 2012-03-29 13:47:53 – ——————————————————– /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET NAMES utf8 */; /*!40014 SET FOREIGN_KEY_CHECKS=0 */; – Dumping database structure for huellas DROP DATABASE IF EXISTS `huellas`; CREATE DATABASE IF NOT EXISTS `huellas` /*!40100 DEFAULT CHARACTER SET latin1 */; USE `huellas`; – Dumping structure for table huellas.huella DROP TABLE IF EXISTS `huella`; CREATE TABLE IF NOT EXISTS `huella` ( `identificacion_usuario` bigint(20) unsigned NOT NULL, `nombres_usuario` varchar(250) NOT NULL, `huella1_usuario` blob NOT NULL, `huella2_usuario` blob NOT NULL, PRIMARY KEY (`identificacion_usuario`), KEY `cedula` (`identificacion_usuario`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; – Data exporting was unselected. /*!40014 SET FOREIGN_KEY_CHECKS=1 */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; Para mayor información consultar esta página: http://napster2011.wordpress.com/2012/03/29/desarrollo-de-un-sistema-de-huella-digitalcon-java-y-mysql/ http://www.soygik.com/como-funciona-un-lector-de-huellas-digital/ OTRO EJEMPLO EN JAVA LLEVADO EN PRÁCTICA EN LA MATERIA ANÁLISIS Y DISEÑO III NOTA: Tengamos en cuenta que ya tenemos instalados los Drivers del lector de huella y el Fingerprint_SDK_Java_2007_Installer.jar Algunos pasos son: 1. Abrir nuestro programa NetBeans 2. Creamos un proyecto en NetBeans con el nombre EjemploLectorHuellas2. 3. Dentro del proyecto crear un paquete de nombre procedimientos y otro de nombre interfaz. Paquete de procedimientos: Paquete de interfaz: 4. Dentro de procedimientos crear una clase (Java Class) llamada Util. 5. En la clase Util se debe capturar el siguiente código: import com.griaule.grfingerjava.FingerprintImage; import com.griaule.grfingerjava.IFingerEventListener; import com.griaule.grfingerjava.IImageEventListener; import com.griaule.grfingerjava.IStatusEventListener; public class Util implements IStatusEventListener, IImageEventListener, IFingerEventListener{ public void onSensorPlug(String idSensor) // evento que se genera al conectar el lector de huella public void onSensorUnplug(String idSensor) // evento que se genera al desconectar el lector de huella public void onImageAcquired(String idSensor, FingerprintImage huellaDigital) // evento que se genera al obtener una imagen de la huella public void onFingerDown(String idSensor) // evento que se genera al colocar un dedo en el lector public void onFingerUp(String idSensor) public void onSensorPlug(String idSensor) { try { GrFingerJava.startCapture(idSensor, this, this); } catch (GrFingerJavaException e) { e.printStackTrace(); } } public void onSensorUnplug(String idSensor) { try { GrFingerJava.stopCapture(idSensor); } catch (GrFingerJavaException e) { e.printStackTrace(); } }… A continuación se muestra una imagen de lo antes mencionado: 6. Crear una clase que se llame File /**Contexto utilizado para la captura, extracción y coincidencia de huellas digitales */ private MatchingContext fingerprintSDK; /**Interfaz de usuario donde se muestra la imagen de la huella*/ private PantallaPrincipal ui; /** Indica si la plantilla o template debe ser extraída automáticamente*/ private boolean autoExtract = true; /** Contiene localmente los datos de la huella capturada */ private ByteArrayInputStream fingerprintData; /**Contiene la longitud del dato de la huella*/ private int fingerprintDataLength; 7. También se debe crear la interfaz de usuario, para ello damos clic derecho en el paquete interfaz y seleccionamos New -> JFrame Form, le damos por nombre 'PantallaPrincipal'.Como se muestra en las siguientes imágenes: 8. Agregamos dos paneles (Huella Digital y Acciones y 4 botones (Verificar, Identificar, Guardar y Salir) de manera que queden parecido a lo siguiente: 9. Nombramos los botones tal cual su etiqueta pero anteponiendo las letras btn, es decir btnVerificar, btnIdentificar y así sucesivamente, el panel de Huella Digital lo nombramos 'panelContenedor'. 10.Por último en la clase Util (por el momento) agregamos un método que nos permita inicializar la captura de las huellas, deberá de quedar así: /** * Inicializa el Fingerprint SDK y habilita la captura de huellas. */ public void inicializarCaptura() { try { fingerprintSDK = new MatchingContext(); //Inicializa la captura de huella digital. GrFingerJava.initializeCapture(this); } catch (Exception e) { //Si ocurre un error se cierra la aplicación. e.printStackTrace(); System.exit(1); } } Todos los paquetes y clases están relacionados entre sí aunque pareciera que son independientes. CONCLUSIÓN No se logró en su totalidad el objetivo que era ver funcionar el lector de huella con la redacción de este código que se llevó a la práctica, pero de algo si estoy segura, que aprendí muchas cosas nuevas como: Instrucciones de código y por supuesto a programar en NetBeans ya que nunca lo había utilizado. Una posible solución para verlo funcionar seria redactarlo mediante consola.