using System.Net.WebSockets; using System.Text; using System.Text.Json; var builder = WebApplication.CreateBuilder(args); // Configurar para escutar em portas específicas builder.WebHost.UseUrls("http://0.0.0.0:8081"); // Adicionar serviços builder.Services.AddCors(options => { options.AddDefaultPolicy(policy => { policy.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod(); }); }); var app = builder.Build(); app.UseCors(); // Pasta para salvar templates var fingerprintPath = Path.Combine(Directory.GetCurrentDirectory(), "Fingerprint"); Directory.CreateDirectory(fingerprintPath); // Storage simples para demonstração var usuariosBiometricos = new Dictionary(); var sessaoAtiva = new Dictionary(); // Carregar usuários existentes na inicialização CarregarUsuariosExistentes(fingerprintPath, usuariosBiometricos); // ================================ // API REST - Como no seu exemplo // ================================ // Status da API app.MapGet("/v1/biometry/status", () => new { Status = "Online", Servidor = Environment.MachineName, Timestamp = DateTime.Now, WebSocket = "ws://localhost:19001", Versao = "1.0.0" }); // Registrar usuário app.MapPost("/v1/biometry/register", async (RegistroBiometrico registro) => { if (usuariosBiometricos.ContainsKey(registro.Matricula)) { return Results.BadRequest(new { Erro = "Usuário já existe", Matricula = registro.Matricula }); } var usuario = new TemplateBiometrico { Matricula = registro.Matricula, Nome = registro.Nome, Template = registro.Template, DataRegistro = DateTime.Now }; usuariosBiometricos[registro.Matricula] = usuario; // Salvar template em arquivo await SalvarTemplateEmArquivo(usuario, fingerprintPath); Console.WriteLine($"✅ Usuário registrado: {registro.Matricula} - {registro.Nome}"); Console.WriteLine($"💾 Template salvo em: Fingerprint/{registro.Matricula}.json"); return Results.Ok(new { Sucesso = true, Mensagem = "Usuário registrado com sucesso", Matricula = registro.Matricula }); }); // Autenticar usuário app.MapPost("/v1/biometry/authenticate", (AutenticacaoBiometrica auth) => { if (!usuariosBiometricos.ContainsKey(auth.Matricula)) { return Results.NotFound(new { Erro = "Usuário não encontrado", Matricula = auth.Matricula }); } var usuario = usuariosBiometricos[auth.Matricula]; // Simular matching (substitua por algoritmo real) var score = SimularMatching(auth.Template, usuario.Template); bool autenticado = score > 75; if (autenticado) { sessaoAtiva[auth.Matricula] = DateTime.Now; Console.WriteLine($"🔐 Login autorizado: {auth.Matricula} - Score: {score}%"); return Results.Ok(new { Sucesso = true, Matricula = auth.Matricula, Nome = usuario.Nome, Score = score, DataLogin = DateTime.Now }); } else { Console.WriteLine($"❌ Login negado: {auth.Matricula} - Score: {score}%"); return Results.Unauthorized(); } }); // Listar usuários app.MapGet("/v1/biometry/users", () => { return Results.Ok(new { TotalUsuarios = usuariosBiometricos.Count, Usuarios = usuariosBiometricos.Values.Select(u => new { u.Matricula, u.Nome, u.DataRegistro, SessaoAtiva = sessaoAtiva.ContainsKey(u.Matricula) }).ToList() }); }); // ================================ // WebSocket - Para tempo real // ================================ app.UseWebSockets(); app.Map("/ws", async (HttpContext context) => { if (context.WebSockets.IsWebSocketRequest) { var webSocket = await context.WebSockets.AcceptWebSocketAsync(); await HandleWebSocket(webSocket); } else { context.Response.StatusCode = 400; } }); Console.WriteLine("🚀 Servidor Biométrico iniciado!"); Console.WriteLine("📡 API REST: http://localhost:8081/v1/biometry/"); Console.WriteLine("🔌 WebSocket: ws://localhost:8081/ws"); Console.WriteLine("📊 Status: http://localhost:8081/v1/biometry/status"); Console.WriteLine("👥 Usuários: http://localhost:8081/v1/biometry/users"); app.Run(); // ================================ // Funções auxiliares // ================================ static async Task SalvarTemplateEmArquivo(TemplateBiometrico usuario, string fingerprintPath) { try { var nomeArquivo = Path.Combine(fingerprintPath, $"{usuario.Matricula}.json"); var dadosParaSalvar = new { usuario.Matricula, usuario.Nome, usuario.Template, usuario.DataRegistro, DataUltimaAtualizacao = DateTime.Now, Versao = "1.0" }; var json = JsonSerializer.Serialize(dadosParaSalvar, new JsonSerializerOptions { WriteIndented = true }); await File.WriteAllTextAsync(nomeArquivo, json); // Também salvar o template como arquivo binário separado var templateBytes = Convert.FromBase64String(usuario.Template); var nomeArquivoBinario = Path.Combine(fingerprintPath, $"{usuario.Matricula}.dat"); await File.WriteAllBytesAsync(nomeArquivoBinario, templateBytes); Console.WriteLine($"💾 Arquivos salvos:"); Console.WriteLine($" 📄 JSON: {nomeArquivo}"); Console.WriteLine($" 🔢 DAT: {nomeArquivoBinario}"); } catch (Exception ex) { Console.WriteLine($"❌ Erro ao salvar template: {ex.Message}"); } } static void CarregarUsuariosExistentes(string fingerprintPath, Dictionary usuariosBiometricos) { try { if (!Directory.Exists(fingerprintPath)) { Console.WriteLine($"📂 Criando pasta: {fingerprintPath}"); return; } var arquivosJson = Directory.GetFiles(fingerprintPath, "*.json"); foreach (var arquivo in arquivosJson) { try { var json = File.ReadAllText(arquivo); var dados = JsonSerializer.Deserialize(json); var usuario = new TemplateBiometrico { Matricula = dados.GetProperty("Matricula").GetString() ?? "", Nome = dados.GetProperty("Nome").GetString() ?? "", Template = dados.GetProperty("Template").GetString() ?? "", DataRegistro = dados.GetProperty("DataRegistro").GetDateTime() }; usuariosBiometricos[usuario.Matricula] = usuario; Console.WriteLine($"📥 Carregado: {usuario.Matricula} - {usuario.Nome}"); } catch (Exception ex) { Console.WriteLine($"⚠️ Erro ao carregar {arquivo}: {ex.Message}"); } } Console.WriteLine($"✅ {usuariosBiometricos.Count} usuários carregados da pasta"); } catch (Exception ex) { Console.WriteLine($"❌ Erro ao carregar usuários: {ex.Message}"); } } async Task HandleWebSocket(WebSocket webSocket) { var buffer = new byte[1024 * 4]; Console.WriteLine("🔌 Cliente WebSocket conectado"); // Enviar mensagem de boas-vindas await EnviarMensagemWebSocket(webSocket, new { Tipo = "conexao", Mensagem = "Conectado ao servidor biométrico", Timestamp = DateTime.Now }); try { while (webSocket.State == WebSocketState.Open) { var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); if (result.MessageType == WebSocketMessageType.Text) { var mensagem = Encoding.UTF8.GetString(buffer, 0, result.Count); Console.WriteLine($"📨 Recebido via WebSocket: {mensagem}"); try { var dados = JsonSerializer.Deserialize(mensagem); await ProcessarComandoWebSocket(webSocket, dados); } catch (Exception ex) { await EnviarMensagemWebSocket(webSocket, new { Tipo = "erro", Mensagem = $"Erro ao processar comando: {ex.Message}" }); } } else if (result.MessageType == WebSocketMessageType.Close) { await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); } } } catch (Exception ex) { Console.WriteLine($"❌ Erro WebSocket: {ex.Message}"); } Console.WriteLine("🔌 Cliente WebSocket desconectado"); } async Task ProcessarComandoWebSocket(WebSocket webSocket, ComandoWebSocket? comando) { if (comando == null) return; switch (comando.Comando?.ToLower()) { case "ping": await EnviarMensagemWebSocket(webSocket, new { Tipo = "pong", Timestamp = DateTime.Now }); break; case "status": await EnviarMensagemWebSocket(webSocket, new { Tipo = "status", UsuariosOnline = sessaoAtiva.Count, TotalUsuarios = usuariosBiometricos.Count, Servidor = Environment.MachineName }); break; case "capturar": // Simular captura de biometria await EnviarMensagemWebSocket(webSocket, new { Tipo = "aguardando_biometria", Mensagem = "Coloque o dedo no sensor...", Matricula = comando.Matricula }); // Simular delay de captura await Task.Delay(2000); await EnviarMensagemWebSocket(webSocket, new { Tipo = "biometria_capturada", Matricula = comando.Matricula, Template = "TEMPLATE_SIMULADO_" + DateTime.Now.Ticks, Qualidade = new Random().Next(70, 95) }); break; default: await EnviarMensagemWebSocket(webSocket, new { Tipo = "erro", Mensagem = $"Comando não reconhecido: {comando.Comando}" }); break; } } async Task EnviarMensagemWebSocket(WebSocket webSocket, object mensagem) { if (webSocket.State == WebSocketState.Open) { var json = JsonSerializer.Serialize(mensagem); var bytes = Encoding.UTF8.GetBytes(json); await webSocket.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Text, true, CancellationToken.None); } } int SimularMatching(string template1, string template2) { if (template1 == template2) return 100; // Simular score baseado em hash dos templates var hash1 = template1.GetHashCode(); var hash2 = template2.GetHashCode(); var similarity = Math.Abs(hash1 - hash2) % 30; return Math.Max(60, 100 - similarity); } // ================================ // Models/DTOs // ================================ public class RegistroBiometrico { public string Matricula { get; set; } = ""; public string Nome { get; set; } = ""; public string Template { get; set; } = ""; } public class AutenticacaoBiometrica { public string Matricula { get; set; } = ""; public string Template { get; set; } = ""; } public class TemplateBiometrico { public string Matricula { get; set; } = ""; public string Nome { get; set; } = ""; public string Template { get; set; } = ""; public DateTime DataRegistro { get; set; } } public class ComandoWebSocket { public string? Comando { get; set; } public string? Matricula { get; set; } public object? Dados { get; set; } }