Mini app authentification avec token jwt

This commit is contained in:
leonard_montalbano 2021-11-10 16:13:52 +01:00
parent e9efcdb236
commit 941cd1f89e
7 changed files with 325 additions and 0 deletions

View File

@ -1,2 +1,18 @@
# Appli_demo
Petite app utilisant l'authentification avec une génération de token jwt.
## Installation et prérequis
Le projet est codé en Python3 il est donc necessaire d'avoir Python3 d'installer sur sa machine. Pour vérifier si
Python3 est bien installer `python3 --version`
Dans un terminal utiliser `pip install -r requirements.txt` (_de préférence dans un environement
virtuel_) afin d'installer les librairies necessaires au bon fonctionnement du projet.
## Lancement du projet
Ensuite ouvrez deux terminal et placer vous à la racine du projet.
Dans le premier taper `flask run` afin de lancer le serveur web.
Et dans l'autre `python3 requetes.py` afin de lancer une batterie de requête pour vérifier le bon
fonctionnement du projet.

146
app.py Normal file
View File

@ -0,0 +1,146 @@
from flask import Flask, request, jsonify, make_response, session, render_template, abort
from flask_restful import Api, Resource
import jwt
from datetime import datetime, timedelta
from functools import wraps
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
api = Api(app)
classes = {'1':
{
'nom': 'A1',
'nombre_eleve': '15',
'eleves': {
'1': ['Mariue', 'Julien', '12'],
'2': ['Koene', 'Morice', '13'],
'3': ['Moatir', 'Pierre', '12'],
'4': ['Poiti', 'Marc', '12'],
'5': ['Areop', 'Tome', '12'],
'6': ['Cenois', 'Louis', '13'],
'7': ['Quotine', 'Maxime', '12'],
'8': ['Reval', 'Adrien', '12'],
'9': ['Fonduri', 'Juliette', '11'],
'10': ['Graconti', 'Marie', '12'],
'11': ['Henvio', 'Louise', '12'],
'12': ['Kenano', 'Bertran', '14'],
'13': ['Vertille', 'Jean-Pierre', '12'],
'14': ['Provern', 'Jean', '14'],
'15': ['Secinoi', 'Celine', '12'],
}
},
'2':
{
'nom': 'A2',
'nombre_eleve': '5',
'eleves': {
'1': ['Benar', 'Leo', '15'],
'2': ['Grovin', 'Benois', '16'],
'3': ['Xeroi', 'Amelie', '15'],
'4': ['Amonie', 'Julien', '14'],
'5': ['Surois', 'Camille', '15']
}
}
}
def token_required(func):
@wraps(func)
def decorated(*args, **kwargs):
token = None
if 'token' in request.headers:
token = request.headers['token']
if not token:
return jsonify({'Alert!': 'Pas de Token!'})
# abort(403, 'pas de token')
try:
payload = jwt.decode(token, app.config['SECRET_KEY'])
except:
# abort(403, 'token invalid')
return make_response(jsonify({'Alert!': 'Token invalid!'}))
return func(*args, **kwargs)
return decorated
@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return 'Déjà connecté'
@app.route('/public')
def public():
return 'Vous êtes bien sur la page public !'
@app.route('/auth', methods=['GET'])
@token_required
def auth():
return 'Vous êtes bien sur la page auth !'
@app.route('/login', methods=['POST'])
def login():
if request.form['username'] and request.form['password'] == '123':
session['logged_in'] = True
token = jwt.encode({
'user': 0
# 'expiration': str(datetime.utcnow() + timedelta(seconds=30))
},
app.config['SECRET_KEY'], algorithm="HS256")
return jsonify({'token': token.decode('utf-8')})
else:
return make_response('Unable to verify', 403, {'WWW-Authenticate': 'Basic realm:"Authentication Failed!'})
class Classes(Resource):
@token_required
def get(self):
return classes
@token_required
def post(self):
return classes
api.add_resource(Classes, "/classes")
class Classe(Resource):
@token_required
def get(self, id_classe):
return classes[id_classe]
@token_required
def post(self, id_classe):
return classes[id_classe]
api.add_resource(Classe, "/classes/<string:id_classe>")
class Eleve(Resource):
@token_required
def get(self, id_classe, id_eleve):
return classes[id_classe]['eleves'][id_eleve]
@token_required
def post(self, id_classe, id_eleve):
return classes[id_classe]['eleves'][id_eleve]
api.add_resource(Eleve, "/<string:id_classe>/<string:id_eleve>")
@app.route("/reset")
def reset():
session.clear()

35
model/data.py Normal file
View File

@ -0,0 +1,35 @@
# data = {'1':
# {
# 'nom': 'A1',
# 'nombre_eleve': '15',
# 'eleves': {
# '1': ['Mariue', 'Julien', '12'],
# '2': ['Koene', 'Morice', '13'],
# '3': ['Moatir', 'Pierre', '12'],
# '4': ['Poiti', 'Marc', '12'],
# '5': ['Areop', 'Tome', '12'],
# '6': ['Cenois', 'Louis', '13'],
# '7': ['Quotine', 'Maxime', '12'],
# '8': ['Reval', 'Adrien', '12'],
# '9': ['Fonduri', 'Juliette', '11'],
# '10': ['Graconti', 'Marie', '12'],
# '11': ['Henvio', 'Louise', '12'],
# '12': ['Kenano', 'Bertran', '14'],
# '13': ['Vertille', 'Jean-Pierre', '12'],
# '14': ['Provern', 'Jean', '14'],
# '15': ['Secinoi', 'Celine', '12'],
# }
# },
# '2':
# {
# 'nom': 'A2',
# 'nombre_eleve': '5',
# 'eleve': {
# '1': ['Benar', 'Leo', '15'],
# '2': ['Grovin', 'Benois', '16'],
# '3': ['Xeroi', 'Amelie', '15'],
# '4': ['Amonie', 'Julien', '14'],
# '5': ['Surois', 'Camille', '15']
# }
# }
# }

60
requetes.py Normal file
View File

@ -0,0 +1,60 @@
import requests
BASE = "http://127.0.0.1:5000/"
login = requests.post(BASE + 'login', {'username': 'leo', 'password': '123'})
token = login.json()['token']
print('Génération du token par une authentification correct: ')
print(token)
print("\n")
HEADERS = {"Authorization": f"Bearer {token}", 'token': token}
public = requests.get(BASE + "public")
print('Accès à la page public qui ne nécessite pas de token: ')
print(public.text)
print("\n")
auth = requests.get(BASE + 'auth', headers=HEADERS)
print('Accès à la page auth qui nécessite un token valide: ')
print(auth.text)
print("\n")
classes = requests.get(BASE + "classes", headers=HEADERS)
print("Les classes : ")
print(classes.json())
print("\n")
classes1 = requests.get(BASE + "classes/1", headers=HEADERS)
print("La classe 1 : ")
print(classes1.json())
print("\n")
eleve = requests.get(BASE + "2/5", headers=HEADERS)
print("L'eleve 5 de la classe 2 : ")
print(eleve.json())
print("\n")
requests.get(BASE + 'reset')
print('Reset de la session pour supprimer le token...')
login2 = requests.post(BASE + 'login', {'username': 'leo', 'password': 'azerty'})
print('Login avec un password qui ne générera pas de token... ')
print("\n")
public2 = requests.get(BASE + "public")
print('Accès à la page public qui ne nécessite pas de token: ')
print(public2.text)
print("\n")
auth2 = requests.get(BASE + 'auth')
print('Accès à la page auth qui nécessite un token valide: ')
print(auth2.json())
print("\n")

44
requirements.txt Normal file
View File

@ -0,0 +1,44 @@
aniso8601==9.0.1
anyio==3.3.4
api==0.0.7
attrs==21.2.0
auth==0.5.3
blinker==1.4
certifi==2021.10.8
charset-normalizer==2.0.7
click==8.0.3
dnspython==2.1.0
eventlet==0.32.0
falcon==3.0.1
fastapi==0.70.0
Flask==2.0.2
Flask-HTTPAuth==4.5.0
Flask-JWT==0.3.2
Flask-RESTful==0.3.9
greenlet==1.1.2
gunicorn==20.1.0
idna==3.3
itsdangerous==2.0.1
Jinja2==3.0.2
JsonForm==0.0.2
jsonschema==4.1.2
JsonSir==0.0.2
MarkupSafe==2.0.1
mongoengine==0.23.1
nose==1.3.7
pydantic==1.8.2
PyJWT==1.4.2
pymongo==3.12.1
pyrsistent==0.18.0
python-dotenv==0.19.1
Python-EasyConfig==0.1.7
pytz==2021.3
PyYAML==6.0
requests==2.26.0
Resource==0.2.1
six==1.16.0
sniffio==1.2.0
starlette==0.16.0
typing-extensions==3.10.0.2
urllib3==1.26.7
Werkzeug==2.0.2

12
templates/base.html Normal file
View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<h1>Mini-App classe</h1>
{% block content %}
{% endblock %}
</body>
</html>

12
templates/login.html Normal file
View File

@ -0,0 +1,12 @@
{% extends 'base.html' %}
{% block content %}
<form action="{{ url_for('login') }}" method="POST">
<label for="username">username</label>
<input type="text" name="username" placeholder="Username"> <br><br>
<label for="password">password</label>
<input type="password" name="password" placeholder="Password"> <br><br>
<input type="submit" value="Login">
</form>
{% endblock %}