Invio di dati da un luogo all'altro? Per la tua tranquillità e la protezione dei tuoi utenti, dovresti proteggerlo con JWT.
Quando crei un'app, è fondamentale proteggere i dati sensibili dall'accesso non autorizzato. Molte moderne applicazioni Web, mobili e cloud utilizzano le API REST come mezzo di comunicazione principale. Di conseguenza, è fondamentale progettare e sviluppare API back-end con la sicurezza in primo piano.
Un approccio efficace alla protezione di un'API REST coinvolge JSON Web Tokens (JWT). Questi token offrono un robusto meccanismo per l'autenticazione e l'autorizzazione degli utenti, contribuendo a salvaguardare le risorse protette dall'accesso da parte di malintenzionati.
Cosa sono i token Web JSON?
Token Web JSON (JWT) è uno standard di sicurezza ampiamente utilizzato. Fornisce un metodo conciso e autonomo per la trasmissione sicura dei dati tra un'app client e un sistema di back-end.
Un'API REST può utilizzare JWT per identificare e autenticare in modo sicuro gli utenti quando effettuano richieste HTTP per accedere a risorse protette.
Un JSON Web Token è costituito da tre parti distinte: l'intestazione, il payload e la firma. Codifica ogni parte e le concatena usando un punto (".").
L'intestazione descrive l'algoritmo crittografico utilizzato per firmare il token, mentre il payload contiene dati sull'utente ed eventuali metadati aggiuntivi.
Infine, la firma, calcolata utilizzando l'intestazione, il payload e la chiave segreta, garantisce l'integrità e l'autenticità del token.
Dopo aver tolto di mezzo le basi dei JWT, creiamo un'API REST Node.js e implementiamo i JWT.
Configurare un'applicazione Express.js e un database MongoDB
Scoprirai qui come costruire una semplice autenticazione API REST che gestisce sia la registrazione che la funzionalità di accesso. Una volta che il processo di accesso ha autenticato un utente, dovrebbe essere in grado di effettuare richieste HTTP a un percorso API protetto.
Puoi trovare il codice del progetto in questo Deposito GitHub.
Per iniziare, creare un server web Expresse installa questi pacchetti:
npm install cors dotenv bycrpt mongoose cookie-parser crypto jsonwebtoken mongodb
Prossimo, creare un database MongoDB O configurare un cluster MongoDB sul cloud. Quindi copiare la stringa di connessione al database, creare un file .env file nella directory principale e incollare la stringa di connessione:
CONNECTION_STRING="stringa di connessione"
Configurare la connessione al database
Crea un nuovo utils/db.js file nella directory principale della cartella del progetto. In questo file, aggiungi il codice seguente per stabilire la connessione al database usando Mongoose.
cost mangusta = richiedere('mangusta');
cost connectDB = asincrono () => {
Tentativo {
aspetta mongoose.connect (processo.env. CONNECTION_STRING);
consolare.tronco d'albero("Connesso a MongoDB!");
} presa (errore) {
consolare.errore("Errore durante la connessione a MongoDB:", errore);
}
};
modulo.exports = connectDB;
Definire il modello di dati
Definisci un semplice schema di dati utente utilizzando Mongoose. Nella directory principale, crea un nuovo file modello/utente.modello.js file e aggiungere il seguente codice.
cost mangusta = richiedere('mangusta');
cost utenteSchema = nuovo mangusta. Schema({
nome utente: Corda,
parola d'ordine: {
tipo: Corda,
necessario: VERO,
unico: VERO,
},
});
cost Utente = mangusta.modello("Utente", userSchema);
modulo.exports = Utente;
Definire i controller per le route API
Le funzioni del controller gestiranno la registrazione e il login; sono una parte sostanziale di questo programma di esempio. Nella directory principale, crea un file controller/userControllers.js file e aggiungere il seguente codice:
- Definire il controller di registrazione utente.
Questo frammento di codice esegue l'hashing della password fornita utilizzando bcrypt e quindi crea un nuovo record utente nel database, memorizzando il nome utente e la password con hash. Se la registrazione va a buon fine, invia una risposta con un messaggio di successo.cost Utente = richiedere('../modelli/utente.modello');
cost bcrypt = richiedere('bcrypt');
cost { generateToken } = richiedere('../middleware/auth');exports.registerUser = asincrono (req, res) => {
cost { username, password } = req.body;Tentativo {
cost hash = aspetta bcrypt.hash (password, 10);
aspetta Utente.create({ nomeutente, parola d'ordine: cancelletto });
res.stato(201).Inviare({ Messaggio: 'Utente registrato con successo' });
} presa (errore) {
consolare.log (errore);
res.stato(500).Inviare({ Messaggio: 'Si è verificato un errore!! ' });
}
}; - Definire un controller di accesso per gestire il processo di accesso dell'utente:
Quando un utente invia una richiesta al /login route, devono passare le proprie credenziali di autenticazione nel corpo della richiesta. Il codice quindi verifica tali credenziali e genera un JSON Web Token. Il token è memorizzato in modo sicuro in un cookie con l'estensione httpSolo flag impostato su vero. Ciò impedisce a JavaScript lato client di accedere al token, proteggendolo da potenziali attacchi XSS (cross-site scripting).exports.loginUser = asincrono (req, res) => {
cost { username, password } = req.body;Tentativo {
cost utente = aspetta User.findOne({ username });
Se (!utente) {
ritorno res.stato(404).Inviare({ Messaggio: 'Utente non trovato' });
}cost passwordMatch = aspetta bcrypt.compare (password, utente.password);
Se (!passwordMatch) {
ritorno res.stato(401).Inviare({ Messaggio: 'Credenziali di accesso non valide' });
}cost carico utile = { ID utente: ID utente };
cost token = generateToken (carico utile);
res.cookie('gettone', gettone, { httpSolo: VERO });
res.stato(200).json({ Messaggio: 'Accesso riuscito'});
} presa (errore) {
consolare.log (errore);
res.stato(500).Inviare({ Messaggio: 'Si è verificato un errore durante l'accesso' });
}
}; - Infine, definire un percorso protetto:
Memorizzando il JWT in un cookie, le successive richieste API dall'utente autenticato includeranno automaticamente il token, consentendo al server di convalidare e autorizzare le richieste.exports.getUsers = asincrono (req, res) => {
Tentativo {
cost utenti = aspetta Utente.find({});
res.json (utenti);
} presa (errore) {
consolare.log (errore);
res.stato(500).Inviare({ Messaggio: 'Si è verificato un errore!!' });
}
};
Crea un middleware di autenticazione
Ora che hai definito un controller di accesso che genera un token JWT in caso di autenticazione riuscita, definisci le funzioni di autenticazione del middleware che genereranno e verificheranno il token JWT.
Nella directory principale, crea una nuova cartella, middleware. All'interno di questa cartella, aggiungi due file: auth.js E config.js.
Aggiungi questo codice a config.js:
cost cripto = richiedere('cripto');
modulo.esporta = {
chiave segreta: crypto.randomBytes(32).accordare('esadecimale')
};
Questo codice genera una nuova chiave segreta casuale ogni volta che viene eseguito. È quindi possibile utilizzare questa chiave segreta per firmare e verificare l'autenticità dei JWT. Una volta che un utente è stato autenticato correttamente, genera e firma un JWT con la chiave segreta. Il server utilizzerà quindi la chiave per verificare che il JWT sia valido.
Aggiungi il seguente codice in auth.js che definisce le funzioni middleware che generano e verificano i JWT.
cost jwt = richiedere('jsonwebtoken');
cost { chiave segreta } = richiedere('./config');cost generareToken = (carico utile) => {
cost token = jwt.sign (payload, secretKey, { scade tra: '1h' });
ritorno gettone ;
};cost verificaToken = (req, res, successivo) => {
cost token = req.cookies.token;Se (!gettone) {
ritorno res.stato(401).json({ Messaggio: "Nessun token fornito" });
}jwt.verify (token, secretKey, (err, decodificato) => {
Se (errare) {
ritorno res.stato(401).json({ Messaggio: 'Gettone non valido' });
}req.userId = decoded.userId;
Prossimo();
});
};
modulo.exports = { generateToken, verificheToken };
IL generateToken La funzione genera un JWT firmando un payload utilizzando una chiave segreta e impostando un tempo di scadenza mentre il verificaToken La funzione funge da middleware per verificare l'autenticità e la validità di un token fornito.
Definire le rotte API
Crea un nuovo route/userRoutes.js file nella directory principale e aggiungere il seguente codice.
cost espresso = richiedere('esprimere');
cost router = espresso. Router();
cost userController = richiedere('../controller/userController');
cost {verificareToken} = richiedere('../middleware/auth');
router.post('/API/registrati', userControllers.registerUser);
router.post('/api/accesso', userControllers.loginUser);
router.get('/api/utenti', verificheToken, userControllers.getUsers);
modulo.exports = router;
Aggiorna il tuo punto di ingresso del server
Aggiorna il tuo server.js file con il seguente codice.
cost espresso = richiedere('esprimere');
cost cor = richiedere('cor');
cost app = espresso();
cost porto = 5000;
richiedere('dotenv'.config();
cost connectDB = richiedere('./utils/db');
cost cookieParser = richiedere('analisi dei cookie');connettiDB();
app.use (express.json());
app.use (express.urlencoded({ esteso: VERO }));
app.use(cors());
app.use (cookieParser());
cost userRoute = richiedere('./percorsi/percorsi utente');
app.use('/', userRoute);
app.listen (porta, () => {
consolare.tronco d'albero(`Il server è in ascolto http://localhost:${porta}`);
});
Per testare l'API REST, avviare il server di sviluppo ed effettuare richieste API agli endpoint definiti:
nodo server.js
Protezione delle API REST di Node.js
La protezione delle API REST di Node.js va oltre il semplice utilizzo dei JWT, sebbene svolgano un ruolo cruciale nell'autenticazione e autorizzazione, è essenziale adottare un approccio di sicurezza olistico alla sicurezza per salvaguardare il tuo back-end sistemi. Oltre ai JWT, dovresti anche prendere in considerazione l'implementazione di HTTPS per crittografare la comunicazione, la convalida e la sanificazione dell'input e molti altri.
Combinando più misure di sicurezza, puoi stabilire un solido framework di sicurezza per il tuo API REST di Node.js e ridurre al minimo il rischio di accessi non autorizzati, violazioni dei dati e altre misure di sicurezza minacce.