Merge branch 'master' of grimbox.be:fred/gwift-book
This commit is contained in:
commit
a88c816fb8
|
@ -8,6 +8,98 @@ Comme on l'a vu dans la partie sur le modèle, nous souhaitons que le créateur
|
||||||
Mécanisme d'authentification
|
Mécanisme d'authentification
|
||||||
****************************
|
****************************
|
||||||
|
|
||||||
|
On peut schématiser le flux d'authentification de la manière suivante :
|
||||||
|
|
||||||
|
En gros:
|
||||||
|
|
||||||
|
. La personne accède à une URL qui est protégée (voir les décorateurs @login_required et le mixin LoginRequiredMixin)
|
||||||
|
. Le framework détecte qu'il est nécessaire pour la personne de se connecter (grâce à un paramètre type LOGIN_URL)
|
||||||
|
. Le framework présente une page de connexion ou un mécanisme d'accès pour la personne (template à définir)
|
||||||
|
. Le framework récupère les informations du formulaire, et les transmets aux différents backends d'authentification, dans l'ordre
|
||||||
|
. Chaque backend va appliquer la méthode `authenticate` en cascade, jusqu'à ce qu'un backend réponde True ou qu'aucun ne réponde
|
||||||
|
. La réponse de la méthode authenticate doit être une instance d'un utilisateur, tel que définit parmi les paramètres généraux de l'application.
|
||||||
|
|
||||||
|
En résumé (bis):
|
||||||
|
|
||||||
|
. Une personne souhaite se connecter;
|
||||||
|
. Les backends d'authentification s'enchaîne jusqu'à trouver une bonne correspondance. Si aucune correspondance n'est trouvée, on envoie la personne sur les roses.
|
||||||
|
. Si OK, on retourne une instance de type curren_user, qui pourra être utilisée de manière uniforme dans l'application.
|
||||||
|
|
||||||
|
Deux exemples :
|
||||||
|
|
||||||
|
. Une authentification par jeton
|
||||||
|
. Une authentification LDAP
|
||||||
|
|
||||||
|
|
||||||
|
[source,python]
|
||||||
|
----
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django.contrib.auth import backends, get_user_model
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from accounts.models import Token <1>
|
||||||
|
|
||||||
|
|
||||||
|
UserModel = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class TokenBackend(backends.ModelBackend):
|
||||||
|
def authenticate(self, request, username=None, password=None, **kwargs):
|
||||||
|
"""Authentifie l'utilisateur sur base d'un jeton qu'il a reçu.
|
||||||
|
|
||||||
|
On regarde la date de validité de chaque jeton avant d'autoriser l'accès.
|
||||||
|
"""
|
||||||
|
token = kwargs.get("token", None)
|
||||||
|
|
||||||
|
current_token = Token.objects.filter(token=token, validity_date__gte=datetime.now()).first()
|
||||||
|
|
||||||
|
if current_token:
|
||||||
|
user = current_token.user
|
||||||
|
|
||||||
|
current_token.last_used_date = datetime.now()
|
||||||
|
current_token.save()
|
||||||
|
|
||||||
|
return user
|
||||||
|
|
||||||
|
return None
|
||||||
|
----
|
||||||
|
<1> Sous-entend qu'on a bien une classe qui permet d'accéder à ces jetons ;-)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[source,python]
|
||||||
|
----
|
||||||
|
from django.contrib.auth import backends, get_user_model
|
||||||
|
|
||||||
|
from ldap3 import Server, Connection, ALL
|
||||||
|
from ldap3.core.exceptions import LDAPPasswordIsMandatoryError
|
||||||
|
|
||||||
|
from config import settings
|
||||||
|
|
||||||
|
|
||||||
|
UserModel = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class LdapBackend(backends.ModelBackend):
|
||||||
|
"""Implémentation du backend LDAP pour la connexion des utilisateurs à l'Active Directory.
|
||||||
|
"""
|
||||||
|
def authenticate(self, request, username=None, password=None, **kwargs):
|
||||||
|
"""Authentifie l'utilisateur au travers du serveur LDAP.
|
||||||
|
"""
|
||||||
|
|
||||||
|
ldap_server = Server(settings.LDAP_SERVER, get_info=ALL)
|
||||||
|
ldap_connection = Connection(ldap_server, user=username, password=password)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not ldap_connection.bind():
|
||||||
|
raise ValueError("Login ou mot de passe incorrect")
|
||||||
|
except (LDAPPasswordIsMandatoryError, ValueError) as ldap_exception:
|
||||||
|
raise ldap_exception
|
||||||
|
|
||||||
|
user, _ = UserModel.objects.get_or_create(username=username)
|
||||||
|
----
|
||||||
|
|
||||||
On peut résumer le mécanisme d'authentification de la manière suivante:
|
On peut résumer le mécanisme d'authentification de la manière suivante:
|
||||||
|
|
||||||
* Si vous voulez modifier les informations liées à un utilisateur, orientez-vous vers la modification du modèle. Comme nous le verrons ci-dessous, il existe trois manières de prendre ces modifications en compte. Voir également `ici <https://docs.djangoproject.com/en/1.9/topics/auth/customizing/>`_.
|
* Si vous voulez modifier les informations liées à un utilisateur, orientez-vous vers la modification du modèle. Comme nous le verrons ci-dessous, il existe trois manières de prendre ces modifications en compte. Voir également `ici <https://docs.djangoproject.com/en/1.9/topics/auth/customizing/>`_.
|
||||||
|
@ -48,7 +140,7 @@ Notez bien qu'**il ne faut pas** spécifier le package ``.models`` dans cette in
|
||||||
Backend
|
Backend
|
||||||
=======
|
=======
|
||||||
|
|
||||||
[blabla...]
|
|
||||||
|
|
||||||
|
|
||||||
*********
|
*********
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
Templates tags
|
||||||
|
--------------
|
||||||
|
|
||||||
|
[source,python]
|
||||||
|
----
|
||||||
|
from django.template.defaultfilters import urlize
|
||||||
|
|
||||||
|
|
||||||
|
class Suggestion(BaseModel):
|
||||||
|
"""Représentation des suggestions.
|
||||||
|
"""
|
||||||
|
created_by = models.ForeignKey(user_model, on_delete=models.DO_NOTHING, verbose_name="Créé par")
|
||||||
|
manager = models.ForeignKey(
|
||||||
|
user_model,
|
||||||
|
on_delete=models.DO_NOTHING,
|
||||||
|
verbose_name="Gestionnaire",
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="managed_by"
|
||||||
|
)
|
||||||
|
subject = models.TextField(verbose_name="Sujet")
|
||||||
|
|
||||||
|
def urlized_subject(self):
|
||||||
|
"""
|
||||||
|
Voir https://docs.djangoproject.com/fr/3.0/howto/custom-template-tags/
|
||||||
|
"""
|
||||||
|
return urlize(self.subject, autoescape=True)
|
||||||
|
----
|
Loading…
Reference in New Issue