Supposons que j'ai une API REST qui est également utilisée pour définir / réinitialiser les mots de passe. Supposons également que cela fonctionne sur une connexion HTTPS. Y a-t-il une bonne raison de ne pas mettre ce mot de passe dans le chemin d'appel, disons également que je vais le coder en BASE64?
Un exemple serait de réinitialiser un mot de passe comme celui-ci:
http://www.example.com/user/joe/resetpassword/OLDPASSWD/NEWPASSWD
Je comprends que BASE64 n'est pas un cryptage, mais je veux seulement protéger le mot de passe pour surfer sur l'épaule dans ce cas.
resetpassword/OLDPASSWD/NEWPASSWD
n'est pas une ressource. C'est l'invocation d'un processus. Vous n'avez pas besoin de tout ranger dans une URL.Réponses:
Un bon serveur enregistre toutes les requêtes qui lui sont envoyées, y compris les URL (souvent, sans partie variable après '?'), L'adresse IP source, le temps d'exécution ... Voulez-vous vraiment que ce journal (potentiellement lu par un large groupe d'administrateurs) contienne des informations sécurisées en tant que mots de passe? Base64 n'est pas un frein contre eux.
la source
Ce que vous proposez n'est ni sécurisé ni RESTful.
@Netch a déjà mentionné le problème des journaux, mais il y a aussi un autre problème dans le fait que vous montrez les mots de passe envoyés par HTTP, ce qui rend trivial la capture de mots de passe avec n'importe quel type de renifleur de fil ou d'attaque de l'homme du milieu.
Lorsque vous effectuez une demande GET à l'aide de REST, les différents éléments de l'URL représentent des éléments plus fins. Votre URL se lit comme si vous renvoyiez une partie NEWPASSWD d'un OLDPASSWD faisant partie d'un mot de passe de réinitialisation. Cela n'a aucun sens sémantique. Les GET ne doivent pas être utilisés pour enregistrer des données.
Vous devriez faire quelque chose comme ça:
POST parce que vous écrivez des données et https parce que vous ne voulez pas qu'elles soient reniflées.
(C'est vraiment la sécurité de la barre basse. Le minimum absolu que vous devriez faire.)
la source
/user/joe/password
c'est un peu mieux mais pas optimal.PUT
, car ilPUT
est idempotent. Mais lorsque le mot de passe a été changé de ensecret
avecsupersecret
succès, la même demande échouera la deuxième fois, c'est doncPOST
correct ici. Bien sûr, comme l'a dit @whirlwin, cette ressource n'est pas bien nommée.Le schéma proposé présente des problèmes dans plusieurs domaines.
Sécurité
Les chemins d'URL sont fréquemment enregistrés; mettre des mots de passe non hachés dans le chemin est une mauvaise pratique.
HTTP
Les informations d'authentification / autorisation doivent apparaître dans l'en-tête d'autorisation. Ou potentiellement, pour les éléments basés sur un navigateur, l'en-tête Cookie.
DU REPOS
Les verbes comme
resetpassword
dans votre URL sont généralement un signe clair d'un paradigme de transfert d'état non représentatif. Une URL doit représenter une ressource. Qu'est-ce que cela signifie pour GETresetpassword
? Ou SUPPRIMER?API
Ce schéma nécessite de toujours connaître le mot de passe précédent. Vous voudrez probablement autoriser plus de cas; par exemple, le mot de passe est perdu.
Vous pouvez utiliser l' authentification de base ou Digest , qui sont des schémas bien compris.
Il ne met pas d'informations ultra-sensibles dans le chemin d'accès et suit les conventions HTTP et REST.
Si vous devez autoriser un autre mode d'autorisation (par exemple, un jeton envoyé via un canal vérifié pour réinitialiser le mot de passe), vous pouvez simplement utiliser un en-tête d'autorisation différent sans avoir à changer quoi que ce soit d'autre.
la source
En dehors de la sécurité, le problème est que ce n'est pas une approche très RESTful.
OLDPASSWD
etNEWPASSWD
ne représentent rien dans votre hiérarchie de ressources et pire encore, l'opération n'est pas idempotente.Vous ne pouvez donc utiliser
POST
que votre verbe et vous ne devez pas inclure les deux mots de passe dans votre chemin d'accès aux ressources.la source
PUT
est donc disqualifié en tant que verbe. Il pourrait être modifié pour fonctionner,PUT
mais dans sa forme actuelle, ce n'est pas le cas.Le problème est d'éviter les mots de passe en texte brut dans vos demandes. Il existe deux options pour répondre aux exigences de service Web reposantes.
1. Hachage côté client
2. Cryptage
Remarque: HTTPS est requis pour les deux options!
la source
Quelles sont les fonctionnalités d'une opération de réinitialisation de mot de passe?
Le point 1 ici signifie que vous ne pouvez pas utiliser GET, vous devez soit POSTER quelque chose représentant l'opération de changement de mot de passe à un URI représentant une ressource qui gère les changements de mot de passe, soit METTRE quelque chose représentant le nouveau mot de passe à un URI représentant le mot de passe ou représentant quelque chose (par exemple le utilisateur) dont ce mot de passe est une caractéristique.
Généralement, nous POSTONS, notamment parce que cela peut être gênant de METTRE quelque chose que nous ne pourrons pas OBTENIR plus tard et bien sûr, nous ne pouvons pas OBTENIR le mot de passe.
Le point 2 sera donc des données représentant le nouveau mot de passe, dans ce qui est POSTé.
Le point 3 signifie que nous devrons autoriser la demande, ce qui signifie que si l'utilisateur est l'utilisateur actuel, nous aurons besoin que le mot de passe actuel nous soit prouvé (mais pas nécessairement recevoir le mot de passe actuel, si par exemple un défi basé sur le hachage a été utilisé pour prouver sa connaissance sans l'envoyer).
L'URI doit donc être quelque chose comme
<http://example.net/changeCurrentUserPassword>
ou<http://example.net/users/joe/changePassword>
.Nous pouvons décider que nous voulons recevoir le mot de passe actuel dans les données POST ainsi que dans le mécanisme d'autorisation général utilisé.
la source