3E e 3I Sia: Sistema di login semplificato che include un CAPTCHA in javascript con nove immagine di diverse categorie

Sistema di login semplificato che include un CAPTCHA in javascript con nove immagine di diverse categorie, animali, frutta, verdura, autovettura, pullman, biciclette. Dalle 9 immagini per entrare nell'area riservata dopo la username e la password, bisogna selezionarne almeno 5




PARTE 1: La Struttura (HTML)

Qui diciamo al browser quali oggetti devono esserci nella pagina.

<!DOCTYPE html>: "Ehi computer, preparati: questo è un documento web moderno."

<html lang="it">: Inizia la pagina e la lingua è l'italiano.

<head>: Questa è la "testa" della pagina. Qui mettiamo le istruzioni segrete che l'utente non vede (come il titolo e lo stile).

<div id="login-screen" class="box">: Creiamo una "scatola" (box) che chiamiamo "schermo di login". È il contenitore principale.

<h2>Area Riservata</h2>: Un titolo grande per dire dove ci troviamo.

<input type="text" id="userInput" ...>: Una casella dove l'utente può scrivere il suo nome.

<input type="password" id="passInput" ...>: Una casella per la password (nasconde i caratteri con dei pallini).

<div id="grid" class="grid"></div>: Un magazzino vuoto. JavaScript lo userà per "appenderci" le 9 foto del CAPTCHA.


<button onclick="checkLogin()">Accedi</button>: Un pulsante. Quando lo premi, chiama la funzione checkLogin (la guardia giurata).


<div id="dashboard" ...>: Questa è la "stanza segreta". Di base è invisibile e si mostrerà solo ai "promossi".


PARTE 2: L'Estetica (CSS)

Qui decidiamo come devono apparire gli oggetti appena creati.

:root { --primary: #2563eb; ... }: Creiamo delle etichette per i colori. Invece di scrivere ogni volta "blu scuro", scriviamo --primary.


body { ... display: flex; ... }: Diciamo alla pagina di mettere tutto perfettamente al centro, sia in orizzontale che in verticale.

.grid { display: grid; grid-template-columns: repeat(3, 1fr); ... }: Questa è la riga più importante della grafica. Dice: "Prendi lo spazio delle foto e dividilo in 3 colonne uguali". Crea la griglia 3x3.

.grid img.selected { border-color: var(--primary); ... }: Dice al browser: "Se una foto viene selezionata, disegnaci intorno un bordo blu". Serve a dare conferma all'utente.

PARTE 3: Il Motore (JavaScript)

Qui diamo gli ordini logici. È la parte che "pensa".

const validUser = "ciccio";: Creiamo una memoria fissa: il nome giusto deve essere "ciccio".

const categories = [...]: Una lista di categorie. Ogni categoria ha un nome (n) e delle parole chiave (q) per cercare le foto su internet.

function loadCaptcha() { ... }: Questa è una "ricetta" che il computer segue per creare il test delle immagini.

currentTarget = categories[Math.floor(...)]: Sceglie a caso una categoria (es. "Auto") e la mostra come istruzione.

for(let i=0; i<5; i++) { ... isCorrect: true }: Un ciclo che conta fino a 5. Per 5 volte cerca una foto corretta e le mette l'etichetta "Vera".

for(let i=0; i<4; i++) { ... isCorrect: false }: Per 4 volte cerca foto di altre categorie e le definisce "False".

pool.sort(() => Math.random() - 0.5): Mescola le 9 foto come un mazzo di carte, altrimenti le 5 giuste sarebbero sempre le prime.

function checkLogin() { ... }: Questa funzione è la "guardia".

if (u !== validUser || p !== validPass): Controlla se hai scritto bene nome e password. Se sbagli, ti rimanda indietro.

selected.forEach(img => { ... }): Il computer passa in rassegna le foto che hai cliccato e conta quante sono quelle con l'etichetta "Vera".

if (selected.length === 5 && correctCount === 5): La condizione finale: "Se hai scelto ESATTAMENTE 5 foto e tutte e 5 sono VERE, allora puoi passare".
Ragionamento e Logica del Programma (Perché si fa così?)

Il programma segue un ragionamento a cascata:

Fiducia Zero: Il computer non si fida di nessuno. Prima di farti entrare, ti chiede due cose diverse: una cosa che sai (password) e una cosa che sai fare (riconoscere immagini).

La Scelta del "5 su 9": Perché 5? Se chiedessimo di trovarne solo 1, un computer cattivo (bot) potrebbe indovinare per caso con 1 probabilità su 9. Chiedendo di trovarne 5 specifiche, la probabilità di indovinare a caso diventa piccolissima (circa 1 su 126). È pura matematica della sicurezza.

Feedback Continuo: Il programma è progettato per "parlare" con l'utente. Se clicchi, la foto cambia colore (CSS). Se sbagli, appare una scritta rossa (JavaScript). Questo serve a non far sentire l'utente perso.

Dinamicità: Le foto non sono caricate nella pagina, ma "pescate" dal web ogni volta. Questo significa che il test è sempre nuovo e non può essere imparato a memoria.

In breve: il programma usa l'HTML per esistere, il CSS per essere comprensibile e il JavaScript per essere sicuro.

La pagina unica comprendente html, Css e Javascript.
Create una pagina html: esempio.html


<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Login Sicuro - CAPTCHA 5/9</title>


<style>
:root { --primary: #2563eb; --error: #e11d48; --bg: #f1f5f9; }
body { font-family: 'Segoe UI', sans-serif; background: var(--bg); display: flex; justify-content: center; padding-top: 30px; }

.box { background: white; padding: 2rem; border-radius: 1rem; box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); width: 380px; }
h2 { text-align: center; margin: 0 0 1rem; color: #1e293b; }
input { width: 100%; padding: 12px; margin-bottom: 10px; border: 1px solid #cbd5e1; border-radius: 8px; box-sizing: border-box; }
.captcha-box { background: #f8fafc; padding: 12px; border-radius: 10px; border: 1px solid #e2e8f0; margin: 15px 0; }
.instruction { font-size: 0.85rem; text-align: center; margin-bottom: 10px; }
.instruction b { color: var(--primary); text-transform: uppercase; font-size: 1rem; }
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.grid img { width: 100%; height: 90px; object-fit: cover; border-radius: 6px; cursor: pointer; border: 4px solid transparent; transition: 0.2s; background: #eee; }
.grid img.selected { border-color: var(--primary); filter: brightness(0.8); }
button { width: 100%; padding: 14px; border: none; border-radius: 8px; background: var(--primary); color: white; font-weight: bold; cursor: pointer; }
#error-msg { color: var(--error); font-size: 0.85rem; text-align: center; margin-top: 10px; min-height: 1.2em; }
#dashboard { display: none; text-align: center; width: 500px; }
</style>
</head>

<body>
<div id="login-screen" class="box">
<h2>Area Riservata</h2>
<input type="text" id="userInput" placeholder="Username (ciccio)">
<input type="password" id="passInput" placeholder="Password (pippo)">
<div class="captcha-box">
<div class="instruction">Seleziona le <b>5 foto</b> di: <br><span id="target-name">...</span></div>
<div id="grid" class="grid"></div>
</div>
<button onclick="checkLogin()">Accedi</button>
<div id="error-msg"></div>
</div>
<div id="dashboard" class="box">
<h1 style="color: #059669">Accesso Eseguito!</h1>
<p>Benvenuto, <b>Ciccio</b>. Sei nella tua dashboard privata.</p>
<button onclick="location.reload()" style="background: #64748b; margin-top: 20px;">Esci</button>
</div>
<script>
const validUser = "ciccio";
const validPass = "pippo";
// Categorie con keyword specifiche per migliorare la precisione della ricerca
const categories = [
{ n: 'Animali', q: 'dog,cat,lion' },

{ n: 'Frutta', q: 'apple,orange,banana' },

{ n: 'Verdura', q: 'broccoli,carrot,lettuce' },

{ n: 'Automobili', q: 'car,sports-car' },

{ n: 'Pullman', q: 'bus,coach' },

{ n: 'Biciclette', q: 'bicycle,bike' }

];

let currentTarget = null;
function loadCaptcha() {
const grid = document.getElementById('grid');
grid.innerHTML = '';
// Scegli categoria obiettivo
currentTarget = categories[Math.floor(Math.random() * categories.length)];
document.getElementById('target-name').innerText = currentTarget.n;
let pool = [];
// FORZA 5 IMMAGINI DELLA CATEGORIA CORRETTA
for(let i=0; i<5; i++) {
pool.push({
url: `https://loremflickr.com/150/150/${currentTarget.q}?lock=${Math.floor(Math.random()*1000)}&i=${i}`,
isCorrect: true
});
}

// AGGIUNGI 4 IMMAGINI DI CATEGORIE DIVERSE
const others = categories.filter(c => c.n !== currentTarget.n);
for(let i=0; i<4; i++) {
let randomCat = others[Math.floor(Math.random() * others.length)];
pool.push({
url: `https://loremflickr.com/150/150/${randomCat.q}?lock=${Math.floor(Math.random()*1000)}&i=${i+5}`,
isCorrect: false
});
}
// Mischia l'ordine in modo casuale
pool.sort(() => Math.random() - 0.5);
// Crea gli elementi IMG
pool.forEach(item => {
const img = document.createElement('img');
img.src = item.url;
img.dataset.correct = item.isCorrect;
img.onclick = function() { this.classList.toggle('selected'); };
grid.appendChild(img);
});
}
function checkLogin() {
const u = document.getElementById('userInput').value;
const p = document.getElementById('passInput').value;
const error = document.getElementById('error-msg');
const selected = document.querySelectorAll('.grid img.selected');

// Verifica credenziali
if (u !== validUser || p !== validPass) {
error.innerText = "Credenziali non valide!";
loadCaptcha();
return;
}

// Verifica CAPTCHA
let correctCount = 0;
selected.forEach(img => {
if(img.dataset.correct === "true") correctCount++;
});
// Deve averne selezionate esattamente 5 e devono essere tutte corrette
if (selected.length === 5 && correctCount === 5) {
document.getElementById('login-screen').style.display = 'none';
document.getElementById('dashboard').style.display = 'block';
} else {
error.innerText = "CAPTCHA errato! Seleziona le 5 foto di " + currentTarget.n;
loadCaptcha();
}
}
window.onload = loadCaptcha;
</script>
</body>
</html>


Il programma che abbiamo realizzato utilizza l'API di LoremFlickr.

Nello specifico, la riga di codice che "chiama" questa API è:
https://loremflickr.com/150/150/${query}?lock=${random}
Ecco una spiegazione analitica di come funziona questa API nel nostro contesto:

1. Che cos'è un'API in questo caso?
Immagina l'API come un cameriere: il tuo programma è il cliente che ordina una foto (es. "Voglio una foto di un gatto") e l'API di LoremFlickr è il cameriere che va in cucina (il suo database di immagini), prende la foto e te la porta sul tavolo (la griglia del tuo sito).

2. Analisi dell'indirizzo (URL) dell'API
Ogni parte dell'indirizzo che abbiamo usato serve a dare un comando preciso:
https://loremflickr.com: È l'indirizzo del server (la cucina).
/150/150/: È il comando di ridimensionamento. Dice all'API: "Non mandarmi la foto originale, ma tagliala esattamente a 150 pixel di larghezza e 150 di altezza". Questo serve a rendere la nostra griglia ordinata.
${currentTarget.q}: È la parola chiave (query). Se la categoria scelta è "Animali", qui ci sarà scritto "dog,cat". L'API cercherà immagini che hanno quel tag.

?lock=${Math.random()}: Questo è il comando di Cache Busting. Senza questo, il browser potrebbe mostrarti sempre la stessa foto salvata in memoria. Aggiungendo un numero casuale, costringiamo l'API a mandarci una foto diversa ogni volta che si apre la pagina.
Perché abbiamo scelto LoremFlickr invece di altre API?

Per uno studente che sta imparando, questa API è ideale per tre motivi:

Semplicità (No Key): Molte API (come Unsplash o Google Images) richiedono una "API Key" (una password segreta) e una registrazione complicata. LoremFlickr è libera e immediata.

Velocità: Risponde molto velocemente alle richieste di immagini casuali.

Flessibilità: Permette di cercare più soggetti contemporaneamente separandoli con una virgola (es. apple,orange), aumentando la varietà del CAPTCHA.
Sintesi del Ragionamento Logico

Il programma non "possiede" le immagini. Le noleggia per un istante dal Web tramite l'API. Quando l'utente ricarica la pagina, il programma fa una nuova telefonata all'API, riceve nuove foto e crea una sfida completamente diversa. Questo rende il sistema sicuro perché un malintenzionato non può prevedere quali foto appariranno.

Commenti

Post popolari in questo blog

Esercizi in Excel e fogli di Google

Le domande (e le risposte) all'orale di informatica esame di stato nei corsi: Sistemi Informativi aziendali (ex programmatori), Itis Informatica (ex Abacus), Liceo Tecnologico