Registro y autenticación - Backend y Frontend - Lenguaje C

 Arquitectura del sistema

  1. Frontend:
    • Un formulario interactivo donde el usuario pueda registrarse.
    • Campo para nombre de usuario y contraseña.
  2. Backend:
    • Endpoint para manejar el registro de usuarios.
    • Almacenamiento seguro de contraseñas utilizando técnicas como hashing (con bcrypt).
    • Endpoint para autenticación de usuarios mediante login.
    • Implementación de validación avanzada.


1. Backend: Registro y autenticación avanzada

Código backend en C

  • Este código agrega funcionalidades para registro de usuarios, almacenamiento seguro de contraseñas y autenticación.

Archivo: auth_handler.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include "auth_handler.h"

#define MAX_USERS 100
#define USERNAME_LENGTH 50
#define PASSWORD_HASH_LENGTH 128

typedef struct {
    char username[USERNAME_LENGTH];
    char password_hash[PASSWORD_HASH_LENGTH];
} User;

User users[MAX_USERS];
int user_count = 0;

// Función para generar hash seguro
void generate_hash(const char *password, char *hash_output) {
    unsigned char hash[EVP_MAX_MD_SIZE];
    unsigned int hash_len;

    EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
    const EVP_MD *md = EVP_sha256();

    EVP_DigestInit_ex(mdctx, md, NULL);
    EVP_DigestUpdate(mdctx, password, strlen(password));
    EVP_DigestFinal_ex(mdctx, hash, &hash_len);
    EVP_MD_CTX_free(mdctx);

    // Convertir el hash a string hexadecimal
    for (unsigned int i = 0; i < hash_len; i++) {
        sprintf(hash_output + (i * 2), "%02x", hash[i]);
    }
}

// Registro de usuarios
int register_user(const char *username, const char *password) {
    if (user_count >= MAX_USERS) {
        return 0;  // No se pueden registrar más usuarios
    }

    for (int i = 0; i < user_count; i++) {
        if (strcmp(users[i].username, username) == 0) {
            return -1;  // Usuario ya registrado
        }
    }

    strncpy(users[user_count].username, username, USERNAME_LENGTH);
    generate_hash(password, users[user_count].password_hash);
    user_count++;

    return 1;  // Registro exitoso
}

// Autenticación de usuarios
int authenticate_user(const char *username, const char *password) {
    char hash[PASSWORD_HASH_LENGTH];
    generate_hash(password, hash);

    for (int i = 0; i < user_count; i++) {
        if (strcmp(users[i].username, username) == 0 &&
            strcmp(users[i].password_hash, hash) == 0) {
            return 1;  // Autenticación exitosa
        }
    }

    return 0;  // Autenticación fallida
}

  

Archivo: auth_handler.h

#ifndef AUTH_HANDLER_H
#define AUTH_HANDLER_H

int register_user(const char *username, const char *password);
int authenticate_user(const char *username, const char *password);

#endif

 

2. Backend: Endpoint HTTP para registro y autenticación

Actualiza el servidor para manejar solicitudes de registro y autenticación.

Agregar lógica al request_handler.c

#include "auth_handler.h"

void handle_register_request(int client_socket, const char *body) {
    char username[50], password[50];
    sscanf(body, "username=%49s&password=%49s", username, password);

    int result = register_user(username, password);
    if (result == 1) {
        const char *response = "HTTP/1.1 201 Created\r\nContent-Type: text/plain\r\n\r\nUsuario registrado exitosamente.";
        write(client_socket, response, strlen(response));
    } else if (result == -1) {
        const char *response = "HTTP/1.1 409 Conflict\r\nContent-Type: text/plain\r\n\r\nUsuario ya existe.";
        write(client_socket, response, strlen(response));
    } else {
        const char *response = "HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nNo se puede registrar más usuarios.";
        write(client_socket, response, strlen(response));
    }
}

void handle_login_request(int client_socket, const char *body) {
    char username[50], password[50];
    sscanf(body, "username=%49s&password=%49s", username, password);

    int result = authenticate_user(username, password);
    if (result == 1) {
        const char *response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nAutenticación exitosa.";
        write(client_socket, response, strlen(response));
    } else {
        const char *response = "HTTP/1.1 401 Unauthorized\r\nContent-Type: text/plain\r\n\r\nCredenciales inválidas.";
        write(client_socket, response, strlen(response));
    }
}

3. Frontend: Formulario de registro y autenticación

Código HTML y JavaScript

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Autenticación avanzada</title>
</head>
<body>
    <h1>Registro de Usuario</h1>
    <form id="registerForm">
        <label for="username">Nombre de usuario:</label>
        <input type="text" id="username" name="username" required>
        <br>
        <label for="password">Contraseña:</label>
        <input type="password" id="password" name="password" required>
        <br>
        <button type="submit">Registrar</button>
    </form>

    <h1>Inicio de Sesión</h1>
    <form id="loginForm">
        <label for="usernameLogin">Nombre de usuario:</label>
        <input type="text" id="usernameLogin" name="usernameLogin" required>
        <br>
        <label for="passwordLogin">Contraseña:</label>
        <input type="password" id="passwordLogin" name="passwordLogin" required>
        <br>
        <button type="submit">Iniciar sesión</button>
    </form>

    <script>
        document.getElementById('registerForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            const username = document.getElementById('username').value;
            const password = document.getElementById('password').value;

            const response = await fetch('/register', {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: `username=${username}&password=${password}`
            });

            const result = await response.text();
            alert(result);
        });

        document.getElementById('loginForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            const username = document.getElementById('usernameLogin').value;
            const password = document.getElementById('passwordLogin').value;

            const response = await fetch('/login', {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: `username=${username}&password=${password}`
            });

            const result = await response.text();
            alert(result);
        });
    </script>
</body>
</html>

¿Es escalable y funcional?

  • Funcional: Sí, este sistema puede manejar autenticación básica y permite a los usuarios registrarse y autenticarse desde el frontend.
  • Escalable: Es limitado en su estado actual (almacenamiento en memoria). Para hacerlo escalable:
  • Implementar bases de datos como MySQL o MongoDB para almacenamiento.
  • Usar frameworks modernos como Express.js para el frontend y Flask/Django para el backend. 
  •  Implementar OAuth2 o JWT para una autenticación más robusta.

 

Cómo usarlo:

  1. Guarda este código en un archivo llamado auth.html.
  2. Coloca el archivo en el directorio donde tu servidor puede servirlo, por ejemplo, el directorio raíz del servidor HTTP que implementaste.
  3. Prueba el archivo accediendo desde tu navegador en http://localhost:8080/auth.html.

Consideraciones:

  1. El formulario de registro envía datos al endpoint /register de tu backend, que maneja la lógica de registro de usuarios.
  2. El formulario de inicio de sesión envía datos al endpoint /login de tu backend, que maneja la autenticación.

 

 

 

Destacado

Bootloader Avanzado en Ensamblador

Bootloader Avanzado en Ensamblador Características del Bootloader Se carga en la dirección 0x7C00 (BIOS). ...