Sistema completo de gestión biométrica para sensores ZKTeco (ZK9500 y compatibles) con interfaz gráfica, base de datos SQLite, encriptación de datos sensibles e integración con APISPeru para autocompletado de datos personales.
- Características Principales
- Requisitos
- Instalación
- Arquitectura del Proyecto
- Documentación de Archivos
- pyzkteco.py
- database.py
- security.py
- zkteco_gui.py
- Guías de Uso
- Capacidades Técnicas
- API Reference
- Ejemplos de Uso
- Configuración Avanzada
- Solución de Problemas
- Seguridad
- Encriptación AES-128: Datos sensibles (DNI, celular, templates biométricos) encriptados en reposo
- Validación de entrada: Prevención de inyección SQL y XSS
- Logging seguro: Enmascaramiento de datos sensibles en logs
- Permisos de archivo: Restricción de acceso a archivos sensibles
- Base de datos SQLite threadsafe: Almacenamiento persistente y seguro
- Migración automática: Compatibilidad con versiones anteriores
- Auditoría completa: Registro de todos los eventos del sistema
- Exportar/Importar: Backup y restauración de templates
- Autocompletado inteligente: Consulta automática de datos personales por DNI
- Validación de DNI: Filtrado de DNIs inválidos antes de consultar la API
- Formateo automático: Nombres y apellidos en formato Title Case
- Optimización de consultas: Validación local para ahorrar consultas API
- Interfaz intuitiva: Diseño moderno y fácil de usar
- Visualización en tiempo real: Muestra imágenes de huellas capturadas
- Registro guiado: Proceso paso a paso para registrar maestros
- Gestión completa: Edición, actualización y eliminación de registros
- Log de actividades: Registro detallado de todas las operaciones
- Captura de huellas: Captura de imagen y template
- Registro (1:3): Combinación de 3 capturas para mayor precisión
- Identificación (1:N): Búsqueda en toda la base de datos
- Comparación (1:1): Verificación entre dos huellas
- Actualización de huellas: Reemplazo de templates existentes
- Windows 10/11 (x64)
- Python 3.7+ (recomendado 3.10+)
- Sensor ZKTeco ZK9500 o compatible
- Conexión USB al sensor
- SDK de ZKTeco instalado (ejecutar
setup.exedel SDK descargarlo con esta URL: "https://new-website-file.s3.ap-southeast-1.amazonaws.com/files/20220725/9774a946c3f659ddf2ae90bc8dadc3eb.rar")
Pillow>=9.0.0
python-dotenv>=1.0.0
requests>=2.31.0
cryptography>=41.0.0
- Ejecuta el archivo
setup.exeque viene con el SDK de ZKTeco - Esto instalará las DLLs necesarias (
libzkfp.dll) en tu sistema - Verifica que la DLL esté en el PATH del sistema o en una ubicación accesible
git clone https://github.com/dithmar1/PyZKTeco
cd PyZKTecopython -m venv env
env\Scripts\activate # Windowspip install -r requirements.txtCrea un archivo .env en la raíz del proyecto:
# API Key de APISPeru (opcional, para autocompletado)
APISPERU_API_KEY=tu_api_key_aqui
# O alternativamente:
API_KEY=tu_api_key_aquipython test_connection.pyPyZKTeco/
├── pyzkteco.py # Wrapper del SDK de ZKTeco (capa baja)
├── database.py # Gestión de base de datos SQLite
├── security.py # Módulo de seguridad y encriptación
├── zkteco_gui.py # Interfaz gráfica principal
├── zkteco_cli.py # Interfaz de línea de comandos
├── requirements.txt # Dependencias del proyecto
├── .env # Variables de entorno (crear manualmente)
├── zkteco.db # Base de datos SQLite (generada automáticamente)
├── .encryption_key # Clave de encriptación (generada automáticamente)
└── Data/ # Directorio de imágenes de validación
└── [Usuario]_[DNI]/
├── img_main.bmp
├── img_validation_1.bmp
├── img_validation_2.bmp
└── img_validation_3.bmp
Propósito: Wrapper de Python para el SDK nativo de ZKTeco. Proporciona una interfaz de alto nivel para interactuar con el sensor biométrico.
sdk = ZKTecoSDK(dll_path=None)dll_path(opcional): Ruta manual alibzkfp.dll. Si esNone, busca automáticamente en ubicaciones comunes.
| Método | Descripción | Retorna |
|---|---|---|
init() |
Inicializa el SDK | bool |
terminate() |
Termina el SDK y libera recursos | bool |
| Método | Descripción | Retorna |
|---|---|---|
get_device_count() |
Obtiene número de dispositivos conectados | int |
open_device(index=0) |
Abre un dispositivo | bool |
close_device() |
Cierra el dispositivo actual | bool |
| Método | Descripción | Retorna |
|---|---|---|
acquire_fingerprint() |
Captura huella (imagen + template) | Optional[Tuple[bytes, bytes]] |
acquire_fingerprint_image() |
Captura solo la imagen | Optional[bytes] |
get_capture_params() |
Obtiene parámetros de captura (width, height, dpi) | Optional[Tuple[int, int, int]] |
| Método | Descripción | Retorna |
|---|---|---|
init_db() |
Inicializa BD en memoria para templates | bool |
close_db() |
Cierra la BD en memoria | bool |
add_template(fid, template) |
Agrega template a la BD | bool |
delete_template(fid) |
Elimina template de la BD | bool |
clear_db() |
Limpia toda la BD | bool |
get_db_count() |
Obtiene número de templates | int |
| Método | Descripción | Retorna |
|---|---|---|
identify(template) |
Identifica huella (1:N) | Optional[Tuple[int, int]] (fid, score) |
match(template1, template2) |
Compara dos templates (1:1) | Optional[int] (score) |
merge_templates(temp1, temp2, temp3) |
Combina 3 templates | Optional[bytes] |
ZKFP_ERR_OK = 0
ZKFP_ERR_NO_DEVICE = -3
ZKFP_ERR_CAPTURE = -8
# ... ver archivo para lista completafrom pyzkteco import ZKTecoSDK
with ZKTecoSDK() as sdk:
sdk.init()
if sdk.open_device(0):
sdk.init_db()
# Capturar huella
result = sdk.acquire_fingerprint()
if result:
img, template = result
print(f"Capturado: {len(template)} bytes")
# Agregar a BD
sdk.add_template(1, template)
# Identificar
match = sdk.identify(template)
if match:
fid, score = match
print(f"Identificado: ID={fid}, Score={score}")Propósito: Gestión threadsafe de base de datos SQLite para almacenamiento persistente de templates biométricos y datos personales.
db = ZKTecoDatabase(db_path="zkteco.db", encrypt_sensitive=True)db_path: Ruta al archivo de base de datosencrypt_sensitive: SiTrue, encripta datos sensibles (DNI, celular, templates)
Tabla: templates
id: INTEGER PRIMARY KEY AUTOINCREMENTfid: INTEGER UNIQUE NOT NULL (Fingerprint ID)nombres: TEXT NOT NULLapellidos: TEXT NOT NULLcelular: TEXT NOT NULL (encriptado siencrypt_sensitive=True)dni: TEXT NOT NULL (encriptado siencrypt_sensitive=True)template: BLOB NOT NULL (template biométrico, encriptado siencrypt_sensitive=True)template_hash: TEXT NOT NULL (SHA-256 del template original)created_at: TIMESTAMP DEFAULT CURRENT_TIMESTAMPupdated_at: TIMESTAMP DEFAULT CURRENT_TIMESTAMPnotes: TEXTactive: INTEGER DEFAULT 1encrypted: INTEGER DEFAULT 0 (flag de encriptación)
Tabla: images (opcional, para historial)
id: INTEGER PRIMARY KEY AUTOINCREMENTfid: INTEGER NOT NULL (FOREIGN KEY)image_data: BLOB NOT NULLwidth,height,dpi: INTEGERcaptured_at: TIMESTAMP
Tabla: events (auditoría)
id: INTEGER PRIMARY KEY AUTOINCREMENTevent_type: TEXT NOT NULLfid: INTEGER (FOREIGN KEY)details: TEXTcreated_at: TIMESTAMP
| Método | Descripción | Retorna |
|---|---|---|
get_next_fid() |
Obtiene siguiente ID disponible | int |
add_template(nombres, apellidos, celular, dni, template, fid=None, notes="") |
Agrega template con validación y encriptación | Tuple[bool, int] |
get_template(fid) |
Obtiene template por ID (desencripta si es necesario) | Optional[Dict] |
get_all_templates(active_only=True) |
Obtiene todos los templates | List[Dict] |
delete_template(fid, soft_delete=True) |
Elimina template (soft delete por defecto) | bool |
clear_all_templates(soft_delete=True) |
Limpia toda la BD | int (cantidad eliminada) |
get_template_count(active_only=True) |
Cuenta templates | int |
save_image(fid, image_data, width, height, dpi) |
Guarda imagen de huella | bool |
get_images(fid, limit=10) |
Obtiene imágenes de un template | List[Dict] |
verify_template_integrity(fid) |
Verifica integridad del template | bool |
export_templates(output_path) |
Exporta todos los templates a JSON | bool |
import_templates(input_path, overwrite=False) |
Importa templates desde JSON | int (cantidad importada) |
get_events(limit=100, event_type=None) |
Obtiene eventos de auditoría | List[Dict] |
- Encriptación automática: DNI, celular y templates se encriptan si
encrypt_sensitive=True - Validación de entrada: Validación estricta usando
validate_input_strict()del módulosecurity - Hash de integridad: SHA-256 del template original para verificación
- Logging seguro: Enmascaramiento de datos sensibles en logs
- Permisos de archivo: Restricción de acceso al archivo de BD
from database import ZKTecoDatabase
# Crear instancia (encriptación habilitada)
db = ZKTecoDatabase("zkteco.db", encrypt_sensitive=True)
# Agregar template
success, fid = db.add_template(
nombres="Juan",
apellidos="Pérez",
celular="987654321",
dni="12345678",
template=template_bytes,
fid=1,
notes="Maestro de matemáticas"
)
# Obtener template (se desencripta automáticamente)
template_data = db.get_template(1)
print(template_data['nombres']) # "Juan"
print(template_data['dni']) # "12345678" (desencriptado)
# Exportar todos los templates
db.export_templates("backup.json")
# Importar templates
imported = db.import_templates("backup.json", overwrite=True)
print(f"Importados: {imported} templates")Propósito: Módulo de seguridad para encriptación, validación, logging seguro y protección de datos sensibles.
security = SecurityManager(key_file=".encryption_key")key_file: Ruta al archivo de clave de encriptación (se genera automáticamente si no existe)
| Método | Descripción | Retorna |
|---|---|---|
encrypt_data(data: bytes) |
Encripta bytes usando Fernet (AES-128) | Optional[bytes] |
decrypt_data(encrypted_data: bytes) |
Desencripta bytes | Optional[bytes] |
encrypt_string(text: str) |
Encripta string (retorna base64) | Optional[str] |
decrypt_string(encrypted_text: str) |
Desencripta string desde base64 | Optional[str] |
| Método | Descripción | Retorna |
|---|---|---|
hash_sensitive_data(data: str) |
Genera hash SHA-256 (irreversible) | str |
mask_dni(dni: str, visible_chars=2) |
Enmascara DNI para logging | str (ej: "73******") |
mask_celular(celular: str, visible_chars=3) |
Enmascara celular para logging | str (ej: "987******") |
sanitize_for_logging(text: str, max_length=50) |
Sanitiza texto para logs | str |
secure_compare(a: bytes, b: bytes) |
Comparación segura (constante en tiempo) | bool |
generate_secure_token(length=32) |
Genera token seguro aleatorio | str |
secure_delete(data: bytes) |
Intenta eliminar datos de memoria | None |
validate_input_strict(text: str, field_type: str, max_length: int = 200)
Valida entrada estrictamente para prevenir inyección y ataques.
field_type:"dni","celular","name","text"- Retorna:
Tuple[bool, str](es_válido, mensaje_error)
Validaciones por tipo:
- DNI: 8 dígitos numéricos, no todos iguales
- Celular: 9 dígitos numéricos, debe comenzar con 9
- Name/Text: Letras, espacios, acentos; filtra patrones peligrosos (SQLi, XSS)
protect_file_permissions(file_path: str)
Establece permisos restrictivos (0o600) en archivos sensibles (solo en sistemas Unix).
from security import SecurityManager, validate_input_strict
# Crear instancia
security = SecurityManager()
# Encriptar datos
encrypted_dni = security.encrypt_string("12345678")
print(encrypted_dni) # Base64 encoded
# Desencriptar
decrypted_dni = security.decrypt_string(encrypted_dni)
print(decrypted_dni) # "12345678"
# Validar entrada
is_valid, error = validate_input_strict("12345678", "dni")
if is_valid:
print("DNI válido")
else:
print(f"Error: {error}")
# Enmascarar para logging
masked = security.mask_dni("12345678")
print(masked) # "12******"Propósito: Interfaz gráfica completa desarrollada con Tkinter para gestión biométrica.
root = tk.Tk()
app = ZKTecoGUI(root)
root.mainloop()1. Panel de Controles (Izquierda)
- Captura de huella
- Guardar template/imagen
- Identificación (1:N)
- Comparación (1:1)
2. Panel de Visualización (Derecha Superior)
- Canvas para mostrar imágenes de huellas
- Controles de zoom (+, -, Reset)
- Información de la imagen (resolución, DPI, tamaño)
3. Lista de Templates (Derecha Inferior)
- Treeview con columnas: ID, Nombres, Apellidos, Celular, DNI, Fecha de Registro
- Botones: Editar Datos, Actualizar Huella, Eliminar, Actualizar Lista
4. Barra de Estado (Inferior)
- Log de actividades con timestamps
- Niveles: INFO, SUCCESS, ERROR, WARNING
5. Menú Principal
- Conexión: Conectar/Desconectar dispositivo
- Registro: Registrar Nuevo Maestro
- Base de Datos: Limpiar BD, Exportar/Importar Templates
| Función | Descripción |
|---|---|
_connect_device() |
Conecta al dispositivo y valida APISPeru |
_disconnect_device() |
Desconecta del dispositivo |
_capture_fingerprint() |
Captura huella en hilo separado |
_show_register_window() |
Muestra ventana de registro |
_start_register() |
Inicia proceso de registro (3 capturas) |
_complete_register() |
Completa registro y guarda en BD |
_identify_fingerprint() |
Identifica huella (1:N) |
_match_fingerprints() |
Compara dos huellas (1:1) |
_edit_template() |
Edita datos personales de un maestro |
_update_fingerprint() |
Actualiza huella de un maestro |
_delete_template() |
Elimina maestro (soft delete) |
_export_templates() |
Exporta templates a JSON |
_import_templates() |
Importa templates desde JSON |
Autocompletado Inteligente:
- Checkbox "Auto Completar con APISPeru"
- Validación de estructura de DNI antes de consultar
- Consulta automática cuando se ingresa DNI de 8 dígitos
- Formateo automático de nombres a Title Case
- Indicador visual del estado de la API
Validación de DNI:
- Filtra DNIs obviamente inválidos (todos iguales, secuencias, patrones repetitivos)
- Ahorra consultas API innecesarias
- Mensajes de error claros
Ventana de Registro:
- Campos: Nombres, Apellidos, Celular (9 dígitos), DNI (8 dígitos)
- Validación en tiempo real
- Progreso de registro (Paso 1/3, 2/3, 3/3)
- Guardado automático de imágenes de validación
Ventana de Éxito:
- Muestra información del registro exitoso
- Aparece en primer plano automáticamente
- Auto-cierre de ventana de registro
Ventana de Edición:
- Edición de datos personales
- Validación de campos
- Actualización en BD
- Guardado automático: 3 imágenes de validación + imagen principal
- Estructura de directorios:
Data/[Nombres]_[Apellidos]_[DNI]/ - Formato: BMP (8-bit grayscale)
- Nombres:
img_validation_1.bmp,img_validation_2.bmp,img_validation_3.bmp,img_main.bmp
# Ejecutar GUI
python zkteco_gui.py
# O programáticamente:
from zkteco_gui import ZKTecoGUI
import tkinter as tk
root = tk.Tk()
app = ZKTecoGUI(root)
root.mainloop()-
Iniciar la aplicación:
python zkteco_gui.py
-
Conectar el dispositivo:
- Menú:
Conexión→Conectar - Espera a que aparezca la ventana de confirmación
- Menú:
-
Registrar un nuevo maestro:
- Menú:
Registro→Registrar Nuevo Maestro - Completa los campos (o usa autocompletado con APISPeru)
- Click en "Iniciar Registro"
- Coloca el dedo 3 veces cuando se solicite
- Espera confirmación de éxito
- Menú:
-
Identificar una huella:
- Click en "Identificar Huella (1:N)"
- Coloca el dedo en el sensor
- El sistema buscará en la base de datos
-
Editar datos de un maestro:
- Selecciona un maestro en la lista
- Click en "Editar Datos"
- Modifica los campos y guarda
-
Configurar API Key:
- Crea archivo
.enven la raíz del proyecto - Agrega:
APISPERU_API_KEY=tu_api_key
- Crea archivo
-
Usar autocompletado:
- Abre ventana de registro
- Activa checkbox "Auto Completar con APISPeru"
- Ingresa DNI de 8 dígitos
- Los campos se completan automáticamente
-
Validación automática:
- El sistema valida la estructura del DNI antes de consultar
- Solo consulta si el DNI pasa la validación local
- Ahorra consultas API innecesarias
Exportar:
- Menú:
Base de Datos→Exportar Templates - Selecciona ubicación y nombre del archivo
- Espera confirmación de exportación
Importar:
- Menú:
Base de Datos→Importar Templates - Selecciona archivo JSON
- Confirma si deseas sobrescribir existentes
- Espera confirmación de importación
- Método:
acquire_fingerprint() - Retorna:
(imagen_bytes, template_bytes) - Resolución: Depende del sensor (típicamente 256x360 @ 500 DPI)
- Formato de imagen: 8-bit grayscale BMP
- Tamaño de template: Variable (típicamente ~512 bytes)
- Proceso: 3 capturas del mismo dedo
- Combinación:
merge_templates()combina los 3 templates - Resultado: Template único más preciso
- Almacenamiento: BD SQLite + BD en memoria del SDK
- Método:
identify(template) - Búsqueda: En toda la base de datos
- Retorna:
(fid, score)si encuentra coincidencia - Umbral: Configurable en el SDK (FP_MTHRESHOLD_CODE)
- Método:
match(template1, template2) - Retorna: Score de coincidencia (>0) o
None - Uso: Verificación de identidad
- Threadsafe: Usa
threading.RLock()ythreading.local() - WAL Mode: Mejor concurrencia
- Transacciones: Context manager para transacciones atómicas
- Soft Delete: Marcado como inactivo en lugar de eliminar
- Auditoría: Registro de todos los eventos
- Detecta columnas faltantes y las agrega
- Compatibilidad con versiones anteriores
- Migración de datos de formato antiguo
- Algoritmo: AES-128 en modo CBC (Fernet)
- Clave: Generada automáticamente, almacenada en
.encryption_key - Datos encriptados: DNI, celular, templates biométricos
- Flag de encriptación: Columna
encrypteden BD
- Entrada estricta: Prevención de SQLi, XSS
- Validación de DNI: Estructura y formato
- Validación de celular: 9 dígitos, comienza con 9
- Sanitización: Limpieza de caracteres peligrosos
- Enmascaramiento: DNI y celular enmascarados en logs
- Sin datos sensibles: No se exponen datos encriptados
- Auditoría: Registro de eventos sin datos sensibles
Ver sección pyzkteco.py para documentación completa.
Ver sección database.py para documentación completa.
Ver sección security.py para documentación completa.
# Ejecutar GUI
python zkteco_gui.py
# Flujo:
# 1. Conectar dispositivo
# 2. Registrar nuevo maestro
# 3. Completar formulario (o usar APISPeru)
# 4. Capturar 3 huellas
# 5. Confirmar registrofrom pyzkteco import ZKTecoSDK
from database import ZKTecoDatabase
import time
# Inicializar
sdk = ZKTecoSDK()
sdk.init()
sdk.open_device(0)
sdk.init_db()
db = ZKTecoDatabase("zkteco.db", encrypt_sensitive=True)
# Registrar maestro
fid = db.get_next_fid()
templates = []
# Capturar 3 veces
for i in range(3):
print(f"Captura {i+1}/3...")
result = sdk.acquire_fingerprint()
if result:
_, template = result
templates.append(template)
time.sleep(1)
# Combinar
merged = sdk.merge_templates(templates[0], templates[1], templates[2])
# Guardar en BD
db.add_template(
nombres="Juan",
apellidos="Pérez",
celular="987654321",
dni="12345678",
template=merged,
fid=fid
)
# Agregar a BD en memoria del SDK
sdk.add_template(fid, merged)
print(f"Registrado con ID: {fid}")from pyzkteco import ZKTecoSDK
from database import ZKTecoDatabase
sdk = ZKTecoSDK()
sdk.init()
sdk.open_device(0)
sdk.init_db()
db = ZKTecoDatabase("zkteco.db")
# Cargar templates a BD en memoria
templates = db.get_all_templates(active_only=True)
for t in templates:
sdk.add_template(t['fid'], t['template'])
# Capturar huella para identificar
result = sdk.acquire_fingerprint()
if result:
_, template = result
# Identificar
match = sdk.identify(template)
if match:
fid, score = match
user = db.get_template(fid)
print(f"Identificado: {user['nombres']} {user['apellidos']}")
print(f"Score: {score}")
else:
print("No encontrado")from database import ZKTecoDatabase
db = ZKTecoDatabase("zkteco.db")
# Exportar backup
db.export_templates("backup_2024.json")
print("Backup creado")
# Restaurar desde backup
imported = db.import_templates("backup_2024.json", overwrite=True)
print(f"Restaurados {imported} templates")# Habilitar encriptación (por defecto)
db = ZKTecoDatabase("zkteco.db", encrypt_sensitive=True)
# Deshabilitar encriptación
db = ZKTecoDatabase("zkteco.db", encrypt_sensitive=False)Archivo .env:
# Opción 1: Usar APISPERU_API_KEY
APISPERU_API_KEY=tu_api_key_aqui
# Opción 2: Usar API_KEY (alternativa)
API_KEY=tu_api_key_aquiValidación de disponibilidad:
- Se valida al iniciar la aplicación
- Se muestra estado en logs al conectar dispositivo
- Checkbox deshabilitado si no está configurado
Ubicación personalizada:
db = ZKTecoDatabase("ruta/personalizada/zkteco.db")Permisos de archivo:
- En sistemas Unix: Se establecen permisos 0o600 automáticamente
- En Windows: Se manejan mediante ACLs del sistema
Causa: La DLL del SDK no está en el PATH o no está instalada.
Solución:
- Ejecuta
setup.exedel SDK de ZKTeco - Verifica que
libzkfp.dllesté en:C:\Windows\System32\C:\Program Files\ZKTeco\- O en el PATH del sistema
- O especifica la ruta manualmente:
sdk = ZKTecoSDK(dll_path="C:\\ruta\\a\\libzkfp.dll")
Causa: El sensor no está conectado o no es reconocido.
Solución:
- Verifica conexión USB
- Instala drivers del sensor
- Prueba otro puerto USB
- Reinicia el sensor
- Verifica que no haya otro software usando el sensor
Causa: El dispositivo está en uso o hay problemas de permisos.
Solución:
- Cierra cualquier otro software que use el sensor
- Ejecuta como administrador si es necesario
- Reinicia el sensor
- Desconecta y reconecta el USB
Causa: No se encontró la API key en .env.
Solución:
- Crea archivo
.enven la raíz del proyecto - Agrega:
APISPERU_API_KEY=tu_api_key - Reinicia la aplicación
Causa: El DNI no pasa la validación de estructura.
Solución:
- Verifica que tenga exactamente 8 dígitos
- No debe tener todos los dígitos iguales
- No debe ser una secuencia obvia
- Si es un DNI real válido, puede ser un falso positivo (la validación es permisiva pero puede fallar)
Causa: Versión antigua de base de datos sin columna encrypted.
Solución:
- El sistema migra automáticamente
- Si persiste, elimina
zkteco.dby crea uno nuevo (pierdes datos)
Causa: Problema de threading o eventos.
Solución:
- Ya está resuelto en la versión actual
- Asegúrate de usar la última versión
- No ejecutes
_on_autocomplete_toggle()automáticamente
-
Protección de la clave de encriptación:
- No commitees
.encryption_keyal repositorio - Mantén permisos restrictivos (0o600)
- Haz backup seguro de la clave
- No commitees
-
Protección de la base de datos:
- Permisos restrictivos en
zkteco.db - Backup encriptado de la BD
- No compartas la BD sin encriptar
- Permisos restrictivos en
-
Logging:
- Los logs no contienen datos sensibles
- Revisa logs antes de compartirlos
- No expongas logs públicamente
-
API Keys:
- No commitees
.enval repositorio - Usa variables de entorno en producción
- Rota las API keys periódicamente
- No commitees
-
Validación de entrada:
- Siempre valida entrada del usuario
- Usa
validate_input_strict()para datos sensibles - Sanitiza antes de mostrar en UI
- Clave de encriptación generada y protegida
-
.encryption_keyen.gitignore -
.enven.gitignore - Base de datos con permisos restrictivos
- API keys configuradas y seguras
- Logs revisados (sin datos sensibles)
- Backup de BD y clave de encriptación
- Validación de entrada habilitada
- Encriptación habilitada (
encrypt_sensitive=True)
- Solo Windows: El SDK de ZKTeco solo está disponible para Windows
- Un dispositivo a la vez: Solo se puede usar un dispositivo simultáneamente
- Templates en memoria: Los templates del SDK están en memoria (volátil), se cargan desde BD al conectar
- Validación de DNI: La validación local es permisiva, puede pasar DNIs inválidos (pero ahorra consultas API)
- Backup regular: Exporta templates periódicamente
- Monitoreo de API: Revisa uso de APISPeru (límite 2000/mes)
- Actualización de huellas: Actualiza huellas periódicamente para mayor precisión
- Logs: Revisa logs regularmente para detectar problemas
Las contribuciones son bienvenidas. Por favor:
- Fork el proyecto
- Crea una rama para tu feature (
git checkout -b feature/AmazingFeature) - Commit tus cambios (
git commit -m 'Add some AmazingFeature') - Push a la rama (
git push origin feature/AmazingFeature) - Abre un Pull Request
Este proyecto está bajo la Licencia GNU GPLv3 Ver archivo LICENSE para más detalles.
Este es un proyecto no oficial. No está afiliado con ZKTeco. El uso es bajo tu propia responsabilidad.
Si tienes preguntas o problemas:
- Abre un issue en GitHub
- Consulta la sección Solución de Problemas
Desarrollado para mejorar la experiencia con sensores biométricos ZKTeco 🚀