JSON tīmekļa marķieri ir viegli lietojami un atkļūdojami, taču tie piedāvā arī iespaidīgu drošības uzlabojumu.

Bojāta autentifikācija joprojām ir pastāvīga ievainojamība mūsdienu tīmekļa lietojumprogrammās — tā joprojām ir augsta OWASP 10 lielāko API drošības risku sarakstā.

Šīs ievainojamības sekas var būt smagas. Tie var piešķirt nesankcionētu piekļuvi sensitīviem datiem un apdraudēt sistēmas integritāti. Lai efektīvi nodrošinātu drošu piekļuvi lietojumprogrammām un to resursiem, ir ļoti svarīgi izmantot spēcīgus autentifikācijas mehānismus.

Uzziniet, kā Flask var ieviest lietotāja autentifikāciju, izmantojot JSON Web Tokens (JWT), populāru un efektīvu uz marķieriem balstītu metodi.

Uz marķieriem balstīta autentifikācija, izmantojot JSON tīmekļa marķierus

Uz marķieri balstīta autentifikācija izmanto šifrētu rakstzīmju virkni, lai apstiprinātu un autorizētu piekļuvi sistēmai vai resursam. Šo autentifikācijas veidu var ieviest, izmantojot dažādas metodes, tostarp sesijas pilnvaras, API atslēgas un JSON tīmekļa marķierus.

Jo īpaši JWT piedāvā drošu un kompaktu pieeju nepieciešamo lietotāju akreditācijas datu pārsūtīšanai starp klienta puses lietojumprogrammām un serveriem.

JWT sastāv no trim galvenajiem komponentiem: galvenes, lietderīgās slodzes un paraksta. Galvenē ir metadati par marķieri, tostarp marķiera kodēšanai izmantotais jaukšanas algoritms.

Kravnesība satur faktiskos lietotāja akreditācijas datus, piemēram, lietotāja ID un atļaujas. Visbeidzot, paraksts nodrošina marķiera derīgumu, pārbaudot tā saturu, izmantojot slepeno atslēgu.

Izmantojot JWT, jūs varat autentificēt lietotājus un saglabāt sesijas datus pašā pilnvarā.

Iestatiet kolbas projektu un MongoDB datu bāzi

Lai sāktu, izveidojiet jaunu projekta direktoriju, izmantojot termināli:

mkdir kolbas projekts
CD kolbas projekts

Tālāk instalējiet virtualenv, lai izveidotu lokālu virtuālo izstrādes vidi savam Flask projektam.

virtualenv venv

Visbeidzot aktivizējiet virtuālo vidi.

# Unix vai MacOS: 
avots venv/bin/activate

# Windows:
.\venv\Scripts\activate

Jūs varat atrast šī projekta kodu GitHub repozitorijs.

Instalējiet nepieciešamās pakotnes

Projekta mapes saknes direktorijā izveidojiet jaunu prasības.txt failu un pievienojiet šīs projekta atkarības:

kolba
pyjwt
python-dotenv
pimongo
bcrypt

Visbeidzot, palaidiet tālāk norādīto komandu, lai instalētu pakotnes. Pārliecinieties, ka jums ir pip (pakešu pārvaldnieks) uzstādīts; ja nē, instalējiet to savā Windows, Mac vai Linux sistēmā.

pip install -r prasības.txt

Izveidojiet MongoDB datu bāzi

Iet uz priekšu un izveidojiet MongoDB datu bāzi. Jūs varat iestatīt vietējo MongoDB datu bāzi, alternatīvi, izveidojiet klasteru MongoDB Atlas — uz mākoņa balstītā MongoDB pakalpojumā.

Kad esat izveidojis datubāzi, nokopējiet savienojuma URI, izveidojiet a .env failu sava projekta saknes direktorijā un pievienojiet to šādi:

MONGO_URI=""

Visbeidzot, konfigurējiet datu bāzes savienojumu no savas lietojumprogrammas Flask. Izveidojiet jaunu utils/db.py failu jūsu projekta saknes direktorijā ar šo kodu:

no pimongo imports Mongoklients

defconnect_to_mongodb(mongo_uri):
klients = MongoClient (mongo_uri)
db = client.get_database("lietotāji")
atgriezties db

Šī funkcija izveido savienojumu ar MongoDB datu bāzi, izmantojot nodrošināto savienojuma URI. Pēc tam tas izveido jaunu lietotājiem kolekciju, ja tā neeksistē, un atgriež atbilstošo datu bāzes gadījumu.

Izveidojiet Flask tīmekļa serveri

Kad datu bāze ir konfigurēta, turpiniet un izveidojiet app.py failu projekta mapes saknes direktorijā un pievienojiet šādu kodu, lai izveidotu lietojumprogrammas Flask instanci.

no kolba imports Kolba
no routes.user_auth imports register_routes
no utils.db imports connect_to_mongodb
imports os
no dotenv imports load_dotenv

lietotne = Kolba (__name__)
load_dotenv()

mongo_uri = os.getenv("MONGO_URI")
db = connect_to_mongodb (mongo_uri)

register_routes (app, db)

ja __nosaukums__ == '__galvenais__':
app.run (debug=Taisnība)

Izveidojiet autentifikācijas API galapunktus

Lai ieviestu lietotāja autentifikāciju savā Flask lietojumprogrammā, ir ļoti svarīgi definēt nepieciešamos API galapunktus, kas apstrādā ar autentifikāciju saistītas darbības.

Tomēr vispirms definējiet lietotāju datu modeli. Lai to izdarītu, izveidojiet jaunu model/user_model.py failu saknes direktorijā un pievienojiet šādu kodu.

no pymongo.kolekcija imports Kolekcija
no bson.objectid imports Objekta ID

klasēLietotājs:
def__tajā__(es, kolekcija: kolekcija, lietotājvārds: str, parole: str):
self.collection = kolekcija
self.username = lietotājvārds
self.password = parole
defsaglabāt(pats):
lietotāja_dati = {
'lietotājvārds': self.lietotājvārds,
'parole': self.parole
}
rezultāts = self.collection.insert_one (lietotāja_dati)
atgriezties str (rezultāts.ievietots_id)

@staticmethod
defatrast_pēc_id(kolekcija: kolekcija, lietotāja_id: str):
atgriezties collection.find_one({'_id': ObjectId (lietotāja_id)})

@staticmethod
defatrast_pēc lietotājvārda(kolekcija: kolekcija, lietotājvārds: str):
atgriezties collection.find_one({'lietotājvārds': lietotājvārds})

Iepriekš minētais kods norāda a Lietotājs klase, kas kalpo kā datu modelis un definē vairākas metodes mijiedarbībai ar MongoDB kolekciju, lai veiktu ar lietotāju saistītas darbības.

  1. The saglabāt metode saglabā MongoDB kolekcijā jaunu lietotāja dokumentu ar norādīto lietotājvārdu un paroli un atgriež ievietotā dokumenta ID.
  2. The atrast_pēc_id un atrast_pēc lietotājvārda metodes izgūst lietotāja dokumentus no kolekcijas, pamatojoties uz attiecīgi norādīto lietotāja ID vai lietotājvārdu.

Definējiet autentifikācijas maršrutus

  1. Sāksim ar reģistrācijas maršruta definēšanu. Šis maršruts MongoDB lietotāju kolekcijai pievienos jaunus lietotāja datus. Saknes direktorijā izveidojiet jaunu routes/user_auth.py failu un šādu kodu.
    imports jwt
    no funkcionālie rīki imports aptinumi
    no kolba imports jsonify, pieprasījums, make_response
    no modeļi.lietotāja_modelis imports Lietotājs
    imports bcrypt
    imports os

    defregister_routes(lietotne, db):
    kolekcija = db.lietotāji
    app.config[SECRET_KEY] = os.urandom(24)

    @app.route('/api/register', method=['POST'])
    defreģistrēties():

    lietotājvārds = request.json.get('lietotājvārds')
    parole = request.json.get('parole')

    esošais_lietotājs = User.find_by_username (kolekcija, lietotājvārds)
    ja esošais_lietotājs:
    atgriezties jsonify({'ziņa': 'Lietotājvārds jau eksistē!'})

    hashed_password = bcrypt.hashpw (password.encode("utf-8"), bcrypt.gensalt())
    new_user = Lietotājs (kolekcija, lietotājvārds, hashed_password.decode("utf-8"))
    lietotāja_id = jauns_lietotājs.save()

    atgriezties jsonify({'ziņa': 'Lietotājs veiksmīgi reģistrēts!', 'Lietotāja ID': Lietotāja ID})

  2. Ieviesiet pieteikšanās funkcionalitāti, lai veiktu autentifikācijas procesu un pārbaudītu lietotāja akreditācijas datus. Zem reģistrācijas maršruta pievienojiet šādu kodu.
     @app.route('/api/login', method=['POST'])
    defPieslēgties():
    lietotājvārds = request.json.get('lietotājvārds')
    parole = request.json.get('parole')
    lietotājs = User.find_by_username (kolekcija, lietotājvārds)
    ja lietotājs:
    ja bcrypt.checkpw (password.encode("utf-8"), lietotājs['parole'].encode("utf-8")):
    marķieris = jwt.encode({'Lietotāja ID': str (lietotājs['_id'])}, app.config[SECRET_KEY], algoritms="HS256")

    atbilde = make_response (jsonify({'ziņa': 'Pieteikšanās veiksmīga!'}))
    response.set_cookie('žetons', marķieris)
    atgriezties atbildi

    atgriezties jsonify({'ziņa': 'Nederīgs lietotājvārds vai parole'})

    Pieteikšanās galapunkts veic divas darbības: tas pārbauda sniegtos lietotāja akreditācijas datus un pēc veiksmīgas autentifikācijas ģenerē šim lietotājam unikālu JWT. Tas atbildē iestata šo marķieri kā sīkfailu kopā ar JSON lietderīgo slodzi, kas norāda uz veiksmīgu pieteikšanos. Ja akreditācijas dati nav derīgi, tas atgriezīs JSON atbildi, lai to norādītu.
  3. Definējiet dekoratora funkciju, kas pārbauda JSON tīmekļa marķierus (JWT), kas nodoti kopā ar turpmākajiem API pieprasījumiem. Pievienojiet zemāk esošo kodu sadaļā register_routes funkciju koda bloks.
    deftoken_required(f):
    @wraps (f)
    defdekorēts(*args, **kwargs):
    marķieris = request.cookies.get('žetons')

    ja marķieris:
    atgriezties jsonify({'ziņa': 'Trūkst marķiera!'}), 401

    mēģināt:
    dati = jwt.decode (token, app.config[SECRET_KEY], algoritmi=["HS256"])
    current_user = User.find_by_id (kolekcija, dati['Lietotāja ID'])
    izņemot jwt. Expired Signature Error:
    atgriezties jsonify({'ziņa': "Token ir beidzies!"}), 401
    izņemot jwt. InvalidTokenError:
    atgriezties jsonify({'ziņa': "Nederīgs marķieris!"}), 401

    atgriezties f (pašreizējais_lietotājs, *args, **kwargs)

    atgriezties dekorēts

    Šī dekoratora funkcija nodrošina derīga JWT marķiera klātbūtni turpmākajos API pieprasījumos. Tas pārbauda, ​​vai marķiera trūkst, vai tā derīguma termiņš ir beidzies vai ir derīgs, un atgriež atbilstošu JSON atbildi, ja tā ir.
  4. Visbeidzot, izveidojiet aizsargātu maršrutu.
     @app.route('/api/users', method=['GET'])
    @token_required
    defget_users(pašreizējais lietotājs):
    lietotāji = saraksts (collection.find({}, {'_id': 0}))
    atgriezties jsonify (lietotāji)

Šis galapunkts apstrādā lietotāja datu izgūšanas loģiku no datu bāzes, taču klientam, kas sūta pieprasījumus, ir jāiekļauj derīgs pilnvaras, lai piekļūtu datiem.

Visbeidzot, palaidiet tālāk norādīto komandu, lai atvērtu izstrādes serveri.

kolbas palaist

Lai pārbaudītu reģistrāciju, pieteikšanos un aizsargāto lietotāju galapunktu, varat izmantot Postman vai jebkuru citu API klientu. Pieprasījumus sūtīt uz http://localhost: 5000/api/un novērojiet atbildes, lai pārbaudītu šo API galapunktu funkcionalitāti.

Vai marķiera autentifikācija ir drošs drošības pasākums?

JSON tīmekļa marķieri nodrošina spēcīgu un efektīvu veidu, kā autentificēt lietotājus jūsu tīmekļa lietotnei. Tomēr ir svarīgi saprast, ka marķiera autentifikācija nav droša; tā ir tikai viena daļa no lielākas drošības mīklas.

Apvienojiet marķiera autentifikāciju ar citām drošības paraugpraksēm. Atcerieties nepārtraukti uzraudzīt un pieņemt konsekventu drošības praksi; jūs ievērojami uzlabosit savu Flask lietojumprogrammu vispārējo drošību.