I token Web JSON sono facili da usare e da eseguire il debug, ma offrono anche un notevole aumento della sicurezza.
L'autenticazione interrotta continua a essere una vulnerabilità persistente nelle moderne applicazioni Web: si colloca ancora ai primi posti tra i 10 principali rischi per la sicurezza delle API di OWASP.
Gli effetti di questa vulnerabilità possono essere gravi. Possono concedere l'accesso non autorizzato a dati sensibili e compromettere l'integrità del sistema. Per garantire in modo efficace un accesso sicuro alle applicazioni e alle relative risorse, è fondamentale utilizzare robusti meccanismi di autenticazione.
Scopri come implementare l'autenticazione utente in Flask utilizzando JSON Web Tokens (JWT), un metodo popolare ed efficace basato su token.
Autenticazione basata su token tramite token Web JSON
L'autenticazione basata su token utilizza una stringa crittografata di caratteri per convalidare e autorizzare l'accesso a un sistema oa una risorsa. Puoi implementare questo tipo di autenticazione utilizzando vari metodi, inclusi token di sessione, chiavi API e token Web JSON.
I JWT, in particolare, offrono un approccio sicuro e compatto per la trasmissione delle credenziali degli utenti richieste tra applicazioni lato client e server.
Un JWT è costituito da tre componenti principali: l'intestazione, il payload e la firma. L'intestazione contiene i metadati relativi al token, incluso l'algoritmo di hashing utilizzato per codificare il token.
Il payload contiene le effettive credenziali dell'utente, come l'ID utente e le autorizzazioni. Infine, la firma garantisce la validità del token verificandone il contenuto mediante una chiave segreta.
Utilizzando i JWT, puoi autenticare gli utenti e archiviare i dati della sessione all'interno del token stesso.
Imposta un progetto Flask e un database MongoDB
Per iniziare, crea una nuova directory del progetto utilizzando un terminale:
progetto pallone mkdir
progetto pallone cd
Quindi, installa virtualenv, per creare un ambiente di sviluppo virtuale locale per il tuo progetto Flask.
virtualenv venv
Infine, attiva l'ambiente virtuale.
# Unix o macOS:
sorgente venv/bin/activate
# Finestre:
.\venv\Scripts\activate
Puoi trovare il codice di questo progetto in questo Deposito GitHub.
Installa i pacchetti richiesti
Nella directory principale della cartella del progetto, crea un nuovo file requisiti.txt file e aggiungi queste dipendenze per il progetto:
borraccia
pyjwt
python-dotenv
pymongo
bcrypt
Infine, esegui il comando seguente per installare i pacchetti. Assicurati di avere pippo (gestore pacchetti) installato; altrimenti, installalo sul tuo sistema Windows, Mac o Linux.
pip install -r requisiti.txt
Crea un database MongoDB
Vai avanti e crea un database MongoDB. Puoi configurare un database MongoDB locale, in alternativa, crea un cluster su MongoDB Atlas, un servizio MongoDB basato su cloud.
Una volta creato il database, copia l'URI di connessione, crea un file .env file nella directory principale del tuo progetto e aggiungilo come segue:
MONGO_URI=""
Infine, configura la connessione al database dall'applicazione Flask. Crea un nuovo utils/db.py file nella directory principale del tuo progetto, con questo codice:
da pymongo importare MongoClient
defconnect_to_mongodb(mongo_uri):
cliente = MongoClient (mongo_uri)
db = client.get_database("utenti")
ritorno db
Questa funzione stabilisce una connessione al database MongoDB utilizzando l'URI di connessione fornito. Quindi crea un nuovo file utenti collection se non esiste e restituisce l'istanza del database corrispondente.
Creare il server Web Flask
Con il database configurato, vai avanti e crea un file app.py file nella directory principale della cartella del progetto e aggiungere il codice seguente per creare un'istanza dell'applicazione Flask.
da borraccia importare Borraccia
da percorsi.user_auth importare register_routes
da utils.db importare connect_to_mongodb
importare os
da dotenv importare load_dotenvapp = Boccetta (__name__)
load_dotenv()mongo_uri = os.getenv('MONGO_URI')
db = connect_to_mongodb (mongo_uri)register_routes (app, db)
Se __nome__ == '__principale__':
app.run (debug=VERO)
Creare gli endpoint dell'API di autenticazione
Per implementare l'autenticazione utente nell'applicazione Flask, è fondamentale definire gli endpoint API necessari che gestiscono le operazioni relative all'autenticazione.
Tuttavia, in primo luogo, definire il modello per i dati degli utenti. Per fare ciò, crea un nuovo file modello/modello_utente.py file nella directory principale e aggiungere il seguente codice.
da pymongo.collezione importare Collezione
da bson.objectid importare ID oggettoclasseUtente:
def__dentro__(self, collezione: Collezione, nome utente: str, password: str):
self.collezione = raccolta
self.username = nome utente
self.password = password
defsalva(se stesso):
dati_utente = {
'nome utente': self.nomeutente,
'parola d'ordine': self.password
}
risultato = self.collection.insert_one (dati_utente)
ritorno str (result.inserted_id)@staticmethod
deffind_by_id(raccolta: Collezione, user_id: str):
ritorno raccolta.find_one({'_id': ObjectId (user_id)})
@staticmethod
deffind_by_username(collezione: Collezione, nome utente: str):
ritorno raccolta.find_one({'nome utente': nome utente})
Il codice sopra specifica a Utente classe che funge da modello di dati e definisce diversi metodi per interagire con una raccolta MongoDB per eseguire operazioni relative all'utente.
- IL salva Il metodo salva un nuovo documento utente con il nome utente e la password forniti nella raccolta MongoDB e restituisce l'ID del documento inserito.
- IL find_by_id E find_by_username I metodi recuperano i documenti dell'utente dalla raccolta in base rispettivamente all'ID utente o al nome utente forniti.
Definire i percorsi di autenticazione
- Iniziamo definendo il percorso di registrazione. Questo percorso aggiungerà nuovi dati utente alla raccolta utenti MongoDB. Nella directory principale, crea un nuovo file percorsi/user_auth.py file e il seguente codice.
importare jwt
da functools importare avvolge
da borraccia importare jsonify, richiesta, make_response
da modelli.modello_utente importare Utente
importare bcrypt
importare osdefregister_routes(app, database):
raccolta = db.users
app.config['CHIAVE SEGRETA'] = os.urandom(24)@app.route('/api/register', metodi=['POST'])
defRegistrati():
nome utente = request.json.get('nome utente')
password = richiesta.json.get('parola d'ordine')
existing_user = User.find_by_username (raccolta, nome utente)
Se utente esistente:
ritorno jsonify({'Messaggio': 'Il nome utente esiste già!'})
hash_password = bcrypt.hashpw (password.encode('utf-8'), bcrypt.gensalt())
new_user = Utente (raccolta, nome utente, hash_password.decode('utf-8'))
user_id = new_user.save()ritorno jsonify({'Messaggio': 'Utente registrato con successo!', 'ID utente': ID utente})
- Implementare la funzionalità di accesso, per gestire il processo di autenticazione e verificare le credenziali dell'utente. Sotto il percorso di registrazione, aggiungi il seguente codice.
L'endpoint di accesso esegue due operazioni: verifica le credenziali utente fornite e, dopo l'autenticazione riuscita, genera un JWT univoco per tale utente. Imposta questo token come cookie nella risposta, insieme a un payload JSON che indica un accesso riuscito. Se le credenziali non sono valide, restituirà una risposta JSON per indicarlo.@app.route('/api/login', metodi=['POST'])
deflogin():
nome utente = request.json.get('nome utente')
password = richiesta.json.get('parola d'ordine')
utente = User.find_by_username (raccolta, nome utente)
Se utente:
Se bcrypt.checkpw (password.encode('utf-8'), utente['parola d'ordine'].codificare('utf-8')):
token = jwt.encode({'ID utente': str (utente['_id'])}, app.config['CHIAVE SEGRETA'], algoritmo='HS256')
risposta = make_response (jsonify({'Messaggio': 'Accesso riuscito!'}))
risposta.set_cookie('gettone', gettone)
ritorno rispostaritorno jsonify({'Messaggio': 'Nome utente o password errati'})
- Definisci una funzione decoratore che verifichi i JSON Web Token (JWT) passati insieme alle successive richieste API. Aggiungi il codice qui sotto all'interno del file register_routes blocco di codice funzione.
Questa funzione decoratore garantisce la presenza di un token JWT valido nelle successive richieste API. Verifica se il token è mancante, scaduto o valido e, in tal caso, restituisce una risposta JSON appropriata.deftoken_richiesto(F):
@avvolge (f)
defdecorato(*args, **kwargs):
token = richiesta.cookies.get('gettone')Senon gettone:
ritorno jsonify({'Messaggio': "Token mancante!"}), 401Tentativo:
dati = jwt.decode (token, app.config['CHIAVE SEGRETA'], algoritmi=['HS256'])
current_user = User.find_by_id (raccolta, dati['ID utente'])
tranne jwt. ExpiredSignatureError:
ritorno jsonify({'Messaggio': "Il token è scaduto!"}), 401
tranne jwt. Errore token non valido:
ritorno jsonify({'Messaggio': 'Gettone non valido!'}), 401ritorno f (utente_corrente, *args, **kwargs)
ritorno decorato
- Infine, crea un percorso protetto.
@app.route('/api/users', metodi=['GET'])
@token_required
defget_users(utente attuale):
utenti = lista (raccolta.find({}, {'_id': 0}))
ritorno jsonify (utenti)
Questo endpoint gestisce la logica per il recupero dei dati utente dal database, ma richiede che il client che invia le richieste includa un token valido per accedere ai dati.
Infine, esegui il comando seguente per avviare il server di sviluppo.
corsa del pallone
Per testare la registrazione, l'accesso e l'endpoint degli utenti protetti, puoi utilizzare Postman o qualsiasi altro client API. Invia richieste a http://localhost: 5000/api/e osserva le risposte per verificare la funzionalità di questi endpoint API.
L'autenticazione tramite token è una misura di sicurezza infallibile?
I token Web JSON forniscono un modo affidabile ed efficace per autenticare gli utenti per la tua app Web. Tuttavia, è importante capire che l'autenticazione tramite token non è infallibile; è solo un pezzo di un puzzle di sicurezza più ampio.
Combina l'autenticazione tramite token con altre best practice di sicurezza. Ricordarsi di monitorare continuamente e adottare pratiche di sicurezza coerenti; migliorerai in modo significativo la sicurezza complessiva delle tue applicazioni Flask.