JSON Web Tokens er enkle å bruke og feilsøke, men de tilbyr også et imponerende sikkerhetsløft.
Ødelagt autentisering fortsetter å være en vedvarende sårbarhet i moderne nettapplikasjoner – den rangerer fortsatt høyt blant OWASPs topp 10 API-sikkerhetsrisikoer.
Effektene av denne sårbarheten kan være alvorlige. De kan gi uautorisert tilgang til sensitive data og kompromittere systemets integritet. For effektivt å sikre sikker tilgang til applikasjoner og deres ressurser, er det viktig at du bruker robuste autentiseringsmekanismer.
Finn ut hvordan du kan implementere brukerautentisering i Flask ved å bruke JSON Web Tokens (JWT), en populær og effektiv token-basert metode.
Token-basert autentisering ved bruk av JSON Web Tokens
Tokenbasert autentisering bruker en kryptert streng med tegn for å validere og autorisere tilgang til et system eller en ressurs. Du kan implementere denne typen autentisering ved hjelp av ulike metoder, inkludert økttokens, API-nøkler og JSON Web Tokens.
Spesielt JWT-er tilbyr en sikker og kompakt tilnærming for å overføre de nødvendige brukernes legitimasjon mellom klientsideapplikasjoner og servere.
En JWT består av tre hovedkomponenter: overskriften, nyttelasten og signaturen. Overskriften inneholder metadata om tokenet, inkludert hashing-algoritmen som brukes til å kode tokenet.
Nyttelasten inneholder den faktiske brukerlegitimasjonen, for eksempel bruker-ID og tillatelser. Til slutt sikrer signaturen gyldigheten av tokenet ved å verifisere innholdet ved hjelp av en hemmelig nøkkel.
Ved å bruke JWT-er kan du autentisere brukere og lagre øktdata alt innenfor selve tokenet.
Sett opp et flaskeprosjekt og en MongoDB-database
For å komme i gang, opprett en ny prosjektkatalog ved hjelp av en terminal:
mkdir kolbe-prosjekt
cd-flaske-prosjekt
Neste, installer virtualenv, for å lage et lokalt virtuelt utviklingsmiljø for ditt Flask-prosjekt.
virtualenv venv
Til slutt, aktiver det virtuelle miljøet.
# Unix eller MacOS:
kilde venv/bin/activate
# Windows:
.\venv\Scripts\aktiver
Du finner dette prosjektets kode i denne GitHub-depot.
Installer de nødvendige pakkene
Opprett en ny i rotkatalogen til prosjektmappen din krav.txt fil, og legg til disse avhengighetene for prosjektet:
kolbe
pyjwt
python-dotenv
pymongo
bcrypt
Til slutt, kjør kommandoen nedenfor for å installere pakkene. Sørg for at du har pip (pakkebehandling) installert; Hvis ikke, installer den på ditt Windows-, Mac- eller Linux-system.
pip install -r requirements.txt
Opprett en MongoDB-database
Gå videre og lag en MongoDB-database. Du kan sette opp en lokal MongoDB-database, alternativt, opprette en klynge på MongoDB Atlas, en skybasert MongoDB-tjeneste.
Når du har opprettet databasen, kopierer du tilkoblings-URIen, oppretter en .env fil i rotkatalogen til prosjektet ditt, og legg den til som følger:
MONGO_URI=""
Til slutt konfigurerer du databasetilkoblingen fra Flask-applikasjonen. Lage en ny utils/db.py fil i rotkatalogen til prosjektet ditt, med denne koden:
fra pymongo import MongoClient
defkoble_til_mongodb(mongo_uri):
klient = MongoClient (mongo_uri)
db = klient.get_database("brukere")
komme tilbake db
Denne funksjonen oppretter en tilkobling til MongoDB-databasen ved å bruke den oppgitte tilkoblings-URIen. Den lager så en ny brukere samling hvis den ikke eksisterer, og returnerer den tilsvarende databaseforekomsten.
Opprett Flask Web Server
Med databasen konfigurert, fortsett og lag en app.py fil i rotkatalogen til prosjektmappen, og legg til følgende kode for å lage en forekomst av Flask-applikasjonen.
fra kolbe import Kolbe
fra routes.user_auth import register_ruter
fra utils.db import koble_til_mongodb
import os
fra dotenv import load_dotenvapp = Kolbe (__navn__)
load_dotenv()mongo_uri = os.getenv('MONGO_URI')
db = koble_til_mongodb (mongo_uri)register_routes (app, db)
hvis __navn__ == '__hoved__':
app.run (debug=ekte)
Opprett Authentication API Endpoints
For å implementere brukerautentisering i Flask-applikasjonen din, er det avgjørende å definere de nødvendige API-endepunktene som håndterer autentiseringsrelaterte operasjoner.
Men først må du definere modellen for brukernes data. For å gjøre det, opprette en ny model/user_model.py fil i rotkatalogen, og legg til følgende kode.
fra pymongo.samling import Samling
fra bson.objektid import ObjectIdklasseBruker:
def__i det__(selv, samling: Samling, brukernavn: str, passord: str):
self.collection = samling
self.username = brukernavn
self.password = passord
deflagre(selv):
user_data = {
'brukernavn': selv.brukernavn,
'passord': selv.passord
}
resultat = self.collection.insert_one (brukerdata)
komme tilbake str (result.inserted_id)@statisk metode
deffinn_etter_id(samling: samling, bruker_id: str):
komme tilbake collection.find_one({'_id': ObjectId (user_id)})
@statisk metode
deffinn_etter_brukernavn(samling: Samling, brukernavn: str):
komme tilbake collection.find_one({'brukernavn': brukernavn})
Koden ovenfor spesifiserer en Bruker klasse som fungerer som en datamodell og definerer flere metoder for å samhandle med en MongoDB-samling for å utføre brukerrelaterte operasjoner.
- De lagre metoden lagrer et nytt brukerdokument med det oppgitte brukernavnet og passordet til MongoDB-samlingen og returnerer IDen til det innsatte dokumentet.
- De finn_etter_id og finn_etter_brukernavn metoder henter brukerdokumenter fra samlingen basert på henholdsvis oppgitt bruker-ID eller brukernavn.
Definer autentiseringsrutene
- La oss starte med å definere registreringsruten. Denne ruten vil legge til nye brukerdata til MongoDB-brukersamlingen. Opprett en ny i rotkatalogen routes/user_auth.py fil og følgende kode.
import jwt
fra funksjonsverktøy import wraps
fra kolbe import jsonify, request, make_response
fra models.user_model import Bruker
import bcrypt
import osdefregister_ruter(app, db):
samling = db.brukere
app.config['SECRET_KEY'] = os.urandom(24)@app.route('/api/register', methods=['POST'])
defregistrere():
brukernavn = request.json.get('brukernavn')
passord = request.json.get('passord')
existerende_bruker = Bruker.finn_av_brukernavn (samling, brukernavn)
hvis eksisterende bruker:
komme tilbake jsonify({'beskjed': 'Brukernavn finnes allerede!'})
hashed_password = bcrypt.hashpw (password.encode("utf-8"), bcrypt.gensalt())
new_user = Bruker (samling, brukernavn, hashed_password.decode("utf-8"))
user_id = new_user.save()komme tilbake jsonify({'beskjed': 'Bruker registrert vellykket!', 'bruker-ID': bruker-ID})
- Implementer påloggingsfunksjonaliteten, for å håndtere autentiseringsprosessen og verifisere brukerlegitimasjon. Legg til følgende kode under registreringsruten.
Påloggingsendepunktet gjør to ting: det verifiserer den oppgitte brukerlegitimasjonen og, etter vellykket autentisering, genererer den en unik JWT for den brukeren. Den setter dette tokenet som en informasjonskapsel i svaret, sammen med en JSON-nyttelast som indikerer en vellykket pålogging. Hvis legitimasjonen er ugyldig, vil den returnere et JSON-svar for å indikere det.@app.route('/api/login', methods=['POST'])
defLogg Inn():
brukernavn = request.json.get('brukernavn')
passord = request.json.get('passord')
bruker = Bruker.finn_av_brukernavn (samling, brukernavn)
hvis bruker:
hvis bcrypt.checkpw (password.encode("utf-8"), bruker['passord'].encode("utf-8")):
token = jwt.encode({'bruker-ID': str (bruker['_id'])}, app.config['SECRET_KEY'], algoritme='HS256')
respons = make_response (jsonify({'beskjed': 'Vellykket innlogging!'}))
response.set_cookie('token', token)
komme tilbake responskomme tilbake jsonify({'beskjed': 'Ugyldig brukernavn eller passord'})
- Definer en dekorasjonsfunksjon som bekrefter JSON Web Tokens (JWTs) som sendes sammen med påfølgende API-forespørsler. Legg til koden nedenfor i register_ruter funksjonskodeblokk.
Denne dekorasjonsfunksjonen sikrer tilstedeværelsen av et gyldig JWT-token i påfølgende API-forespørsler. Den sjekker om tokenet mangler, er utløpt eller gyldig, og returnerer et passende JSON-svar hvis det er det.deftoken_required(f):
@omslag (f)
defdekorert(*args, **kwargs):
token = request.cookies.get('token')hvisikke token:
komme tilbake jsonify({'beskjed': 'Token mangler!'}), 401prøve:
data = jwt.decode (token, app.config['SECRET_KEY'], algoritmer=['HS256'])
current_user = User.find_by_id (innsamling, data['bruker-ID'])
unntatt jwt. ExpiredSignatureError:
komme tilbake jsonify({'beskjed': 'Token har utløpt!'}), 401
unntatt jwt. InvalidTokenError:
komme tilbake jsonify({'beskjed': 'Ugyldig token!'}), 401komme tilbake f (current_user, *args, **kwargs)
komme tilbake dekorert
- Lag til slutt en beskyttet rute.
@app.route('/api/users', methods=['GET'])
@token_required
defget_users(nåværende bruker):
brukere = liste (collection.find({}, {'_id': 0}))
komme tilbake jsonify (brukere)
Dette endepunktet håndterer logikken for å hente brukerdata fra databasen, men det krever at klienten som sender forespørsler inkluderer et gyldig token for å få tilgang til dataene.
Til slutt, kjør kommandoen nedenfor for å spinne opp utviklingsserveren.
kolbe løpe
For å teste registreringen, påloggingen og de beskyttede brukernes endepunkt, kan du bruke Postman eller en annen API-klient. Send forespørsler til http://localhost: 5000/api/og observer svarene for å bekrefte funksjonaliteten til disse API-endepunktene.
Er tokenautentisering et idiotsikkert sikkerhetstiltak?
JSON Web Tokens gir en robust og effektiv måte å autentisere brukere for nettappen din på. Det er imidlertid viktig å forstå at token-autentisering ikke er idiotsikker; det er bare én del av et større sikkerhetspuslespill.
Kombiner token-autentisering med andre beste fremgangsmåter for sikkerhet. Husk å overvåke kontinuerlig, og vedta konsekvente sikkerhetspraksis; du vil forbedre den generelle sikkerheten til Flask-applikasjonene dine betydelig.