Est-il possible d’accélérer la fonction d’authentification dans Django?

Nous utilisons django pour créer un front-end de webservice json pour mysql. Nous avons apache et django sur une instance EC2 et MySQL sur une instance RDS. Nous avons commencé à évaluer les performances en utilisant apache bench et avons obtenu de très mauvais résultats. Nous avons également remarqué que lors de l’exécution des tests, notre instance apache / django passe à 100% du processeur à très faible charge et que l’instance MySQL ne dépasse jamais 2% du processeur.

Nous essayons de donner un sens à cela et d’isoler le problème, nous avons donc fait plusieurs tests ab:

  1. Une demande pour une page html statique à partir de apache – ~ 2000 requêtes / seconde.
  2. Une requête qui exécute une petite fonction python dans django, et aucune interaction db – ~ 1000 requêtes / seconde.
  3. Une requête qui exécute une de nos fonctions django webservice qui appelle authentifier, puis effectue une requête très simple pour récupérer un enregistrement d’une table – 11 requêtes / seconde
  4. Identique à 3, mais commente l’appel à l’authentification – 95 requêtes / seconde.

Pourquoi l’authentification est-elle si lente? Est-ce qu’il écrit des données sur la firebase database, trouvant un milliard de chiffres de pi, quoi?

Nous aimerions garder l’appel pour s’authentifier dans ces fonctions, parce que nous ne voulons pas les laisser ouverts à quiconque peut deviner l’url, etc. Quelqu’un at-il remarqué que l’authentification est lente, il?

Merci beaucoup!

Je ne suis pas un expert de l’authentification et de la sécurité, mais voici quelques idées expliquant pourquoi cela pourrait se produire et peut-être comment augmenter quelque peu les performances.

Étant donné que les mots de passe sont stockés dans la firebase database, leur mot de passe en texte clair n’est pas stocké, à la place, pour que leur stockage soit sécurisé. De cette façon, vous pouvez toujours valider la connexion de l’utilisateur en comparant le hachage calculé du mot de passe saisi à celui stocké dans la firebase database. Cela augmente la sécurité de sorte que si une partie malveillante obtient une copie de la firebase database, le seul moyen de décoder les mots de passe en texte brut consiste à utiliser des tables arc-en-ciel ou une attaque en force.

C’est là que les choses deviennent intéressantes. Selon la loi de Moore, les ordinateurs deviennent de plus en plus rapides, par conséquent les fonctions de hachage deviennent beaucoup moins chères en termes de temps, en particulier les fonctions de hachage rapides comme md5 ou sha1. Cela pose un problème car, toute la puissance de calcul disponible aujourd’hui combinée à des fonctions de hachage rapides, les pirates informatiques peuvent facilement utiliser des mots de passe hachés en mode brut. Pour lutter contre cela, deux choses peuvent être faites. Il suffit de boucler la fonction de hachage plusieurs fois (la sortie du hachage est renvoyée dans le hachage). Ce n’est cependant pas très efficace car cela ne fait qu’accroître la complexité de la fonction de hachage par une constante. C’est pourquoi la seconde approche, qui consiste à rendre la fonction de hachage réelle plus complexe et coûteuse en calculs, est préférable. Ayant une fonction plus complexe, il faut plus de temps pour calculer le hachage. Même si cela prend une seconde à calculer, ce n’est pas un gros problème pour les utilisateurs finaux, mais c’est un gros problème pour les attaques par force brute car des millions de hachages doivent être calculés. C’est pourquoi, à partir de Django 1.4, il utilise une fonction très coûteuse appelée PBKDF2.

Pour revenir à votre réponse. C’est à cause de cette fonction, lorsque vous activez l’authentification, votre numéro de référence tombe en panne et votre processeur augmente.

Voici quelques moyens d’augmenter la performance.

  • À partir de Django 1.4, vous pouvez modifier la fonction d’authentification par défaut ( docs ). Si vous n’avez pas besoin de beaucoup de sécurité, vous pouvez modifier la fonction par défaut pour qu’elle soit SHA1 ou MD5. Cela devrait augmenter les performances, mais gardez à l’esprit que la sécurité sera beaucoup plus faible. Mon opinion personnelle est que la sécurité est importante et vaut le temps supplémentaire, mais si cela ne se justifie pas dans votre application, c’est quelque chose que vous voudrez peut-être envisager.
  • Utiliser les sessions La fonction de hachage coûteuse est uniquement calculée lors de la connexion initiale. Une fois que l’utilisateur se connecte, une session est créée pour cette session et un cookie est envoyé à l’utilisateur avec l’identifiant de session. Ensuite, lors des requêtes suivantes, l’utilisateur télécharge un cookie et si la session n’a pas encore expiré, l’utilisateur est automatiquement authentifié (ne vous inquiétez pas de la sécurité car les données de session sont signées …). Le fait est que la vérification de session est BEAUCOUP moins coûteuse en calcul comparée au calcul de la fonction de hachage coûteuse. Je suppose que dans les tests ab, vous n’avez pas envoyé de cookie de session. Essayez de faire des tests en ajoutant un cookie de session et voyez comment cela fonctionne. Si l’envoi de cookies n’est pas vraiment une option puisque vous créez une API JSON, vous pouvez modifier le back-end de la session pour accepter les données de session via un paramètre GET de session au lieu d’un cookie. Pas sûr cependant quelles sont les ramifications de sécurité de faire cela.
  • Passez à nginx. Je ne suis pas un expert en déploiement mais, selon mon expérience, nginx est beaucoup plus rapide et convivial que Django par rapport à Apache. Un des avantages qui pourrait vous intéresser est la capacité de nginx à avoir plusieurs processus de travail et sa capacité à utiliser proxy_pass pour passer des requêtes aux processus Django. Si vous avez plusieurs processus de travail, vous pouvez diriger chaque travailleur vers un processus Django distinct via proxy_pass, ce qui appenda effectivement le multitraitement à Django. Une autre alternative est que si vous utilisez quelque chose comme gevent serveur WSGI, vous pouvez créer un pool dans le processus Django, ce qui pourrait également augmenter les performances. Vous ne savez pas si l’un de ces éléments augmentera considérablement vos performances, car la charge de votre processeur est déjà de 100%, mais cela pourrait être quelque chose à examiner.