Question

Je crée un site PHP qui implique les utilisateurs de signer, et je me demande sur les meilleures pratiques pour les codes « de confirmation par courrier électronique ».

Les nouveaux utilisateurs doivent confirmer leurs adresses e-mail - Je le fais en générant un code et l'envoyer à l'utilisateur dans un e-mail, qu'il peut ensuite utiliser pour activer son compte. Plutôt que de stocker cette clé dans une base de données, j'utilise une petite solution à portée de main: le code est le résultat de:

md5("xxxxxxxxx".$username."xxxxxxxxxxx".$timestamp."xxxxxxxxx");

Où $ timestamp fait référence à l'heure de création d'utilisateur. Dans l'ensemble, je suis assez content de cela, mais je suis arrivé à penser, est-ce assez sûr? Qu'en est-il la possibilité de collisions? Et je dois aussi générer des codes pour la réinitialisation, etc. Si j'ai utilisé une méthode similaire, une collision peut entraîner un utilisateur par inadvertance la réinitialisation du mot de passe d'un autre utilisateur. Et ça ne va pas.

Alors, comment faites-vous ces choses? Mes pensées était une table au format suivant:

codePK (int, a-I), userID (int), type (int), code (varchar 32), date (timestamp)

Le 'type' serait 1, 2 ou 3 sens "activation", "changement de courrier électronique" ou "réinitialisation de mot de passe". Est-ce une bonne façon de le faire? Avez-vous une meilleure façon?

En utilisant une méthode similaire à ce qui précède, pourrais-je supprimer automatiquement quoi que ce soit plus de deux jours sans utiliser d'exécuter des tâches? Mon hôte (nearlyfreespeech.net) ne les supporte pas. Si possible, je voudrais éviter d'avoir un emploi sur Cron un hôte externe qui wget est un script qui supprime les choses, comme c'est juste en désordre = P.

Merci!
Mala

Mise à jour:
Pour clarifier: Je me suis rendu compte de la seule façon d'aller en toute sécurité et en toute sécurité de cette tâche est à l'aide d'une base de données, ce qui est la fonction d'origine a essayé d'éviter. Ma question porte sur la façon dont la table (ou tables?) Devrait être structuré. Quelqu'un m'a proposé de faire disparaître codePK et juste faire le code PK. Donc en bref, ma question est: est-ce que vous faites

Était-ce utile?

La solution

Quand je besoin de ce genre de trucs, il est normalement l'une des deux raisons, à la fois que vous avez mentionnés:

  1. En tant que clé utilisée pour les courriels de vérification envoyé à l'utilisateur
  2. En tant que clé utilisée pour les liens de mot de passe reset

Bien sûr, il y aurait de nombreuses autres occasions où vous envisagez d'utiliser une telle construction.

Tout d'abord, vous devriez toujours utiliser une sorte de sel qui est caché et que vous seul connaissez. Notez que ce sel doit être différent pour chaque utilisateur. Le sel pourrait par exemple être calculé comme sha256(something random). Ce sel doit ensuite être stocké dans la base de données ainsi que le nom d'utilisateur et mot de passe (avec le sel haché).

Ce que je fais lors de l'envoi du lien de réinitialisation de mot de passe est de créer un autre sel (ne donne pas l'accès des utilisateurs à quoi que ce soit haché avec votre sel. Il connaît son mot de passe, en utilisant bruteforce il pourrait comprendre éventuellement votre sel). L'autre sel, qui est essentiellement seulement un hachage d'une chaîne aléatoire (vous voudrez peut-être aller pour md5 ici, comme vous l'avez mentionné que la longueur est un problème), si vous enregistrez dans votre base de données.

Souvent, vous pouvez simplement sortir avec l'ajout d'une colonne supplémentaire à votre table d'utilisateurs. Mais cela a aussi quelques problèmes, surtout qu'une fois que le mot de passe a été remis à zéro ou l'utilisateur a été activé, vous enlèverez la clé de la base de données, ce qui se traduit dans la plupart des lignes ayant des valeurs nulles, ce qui provoque à son tour une autre difficulté .

Ce que cela se résume essentiellement à:

  • Hash vos mots de passe des utilisateurs à l'aide d'un sel unique de-pour-le-utilisateur ( et peut-être un sel secret global,).
  • Générer une clé en hachant un certain nombre de sources aléatoires ou pseudo-aléatoires comme les estampilles, mt_rand() ou même random.org si vous voulez vraiment des choses au hasard.
  • Ne jamais utiliser votre sel global ou le sel qui est unique à l'utilisateur pour hachant quoi que ce soit que l'utilisateur a accès à, y compris les touches de réinitialisation de mot de passe, les clés d'activation, etc.

S'il vous plaît pas que je suis pas un expert en sécurité, et je l'ai probablement oublié un certain nombre de choses, et je l'ai dit certaines choses très mauvaises pratiques. Juste mes 5 cents; -)

Autres conseils

Pourquoi utiliser l'une des données de l'utilisateur comme base de la clé d'autorisation?

Je suppose que vous stockez les données activées de-dans une base de données alors pourquoi ne pas simplement ajouter un enregistrement supplémentaire qui est simplement une clé aléatoire (peut-être un de md5'ed uniqid avec quelques manipulations supplémentaires), puis vérifiez contre cela?

Il était assez sûr jusqu'à jusqu'au point où vous avez publié votre méthode sur Internet! En effet, vous comptiez sur la sécurité par l'obscurité, ce qui est une bonne idée.

Vous devez utiliser une sorte de fonction de hachage à clé ou MAC idéalement, qui intègre une clé secrète connue uniquement pour vous.

Pourquoi ne pas faire l'index de champ code unique? Donc, il n'y aura jamais collsisions?

En outre, si vous n'avez pas besoin de créer hachage de l'entrée d'utilisateur et correspondre à hachage de base de données (confirmation par email, mot de passe réinitialiser etc) - vous pouvez ajouter chaîne aléatoire au corps de hachage, comme md5('xxx'.$username.'xxx'.time().'xxx'.rand())

Pourquoi ne pas demander à l'utilisateur d'entrer son nom d'utilisateur et leur code, éliminant ainsi tout problème de collision? Vous ne perdez rien sage sécurité que vous demandez toujours la clé qu'ils obtiendraient de l'e-mail, mais vous souhaitez les arrêter d'être en mesure de réinitialiser les autres mots de passe des utilisateurs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top