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_dotenv

app = 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 ObjectId

klasseBruker:
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.

  1. De lagre metoden lagrer et nytt brukerdokument med det oppgitte brukernavnet og passordet til MongoDB-samlingen og returnerer IDen til det innsatte dokumentet.
  2. De finn_etter_id og finn_etter_brukernavn metoder henter brukerdokumenter fra samlingen basert på henholdsvis oppgitt bruker-ID eller brukernavn.

Definer autentiseringsrutene

  1. 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 os

    defregister_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})

  2. Implementer påloggingsfunksjonaliteten, for å håndtere autentiseringsprosessen og verifisere brukerlegitimasjon. Legg til følgende kode under registreringsruten.
     @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 respons

    komme tilbake jsonify({'beskjed': 'Ugyldig brukernavn eller passord'})

    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.
  3. 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.
    deftoken_required(f):
    @omslag (f)
    defdekorert(*args, **kwargs):
    token = request.cookies.get('token')

    hvisikke token:
    komme tilbake jsonify({'beskjed': 'Token mangler!'}), 401

    prø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!'}), 401

    komme tilbake f (current_user, *args, **kwargs)

    komme tilbake dekorert

    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.
  4. 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.