Générer des guides dans Ruby

142

J'ai un problème qui est vraiment facilement résolu avec Guids.

En particulier, pour un flux de travail de réinitialisation de mot de passe, je souhaite envoyer un jeton Guid à l'e-mail d'un utilisateur et lui demander de réinitialiser son mot de passe à l'aide du jeton. Étant donné que les guids sont uniques, cela est assez sécurisé et m'évite d'envoyer les mots de passe des gens par courrier électronique, ce qui est risqué.

J'ai remarqué qu'il y a un joyau Guid pour Ruby; mais il a l'air assez vieux, et il écrit des choses dans le système de fichiers.

Est-ce que quelqu'un connaît d'autres gemmes qui peuvent créer un identifiant unique au monde?

Je sais que je peux simplement me rabattre sur:

(0..16).to_a.map{|a| rand(16).to_s(16)}.join 

Mais cela ne semble pas vraiment être un GUID approprié ...

Sam Safran
la source
1
Utiliser une chaîne aléatoire comme celle-là ne serait pas tout à fait correct; certains bits de l'UUID spécifient la variante et la version. Pour un UUID aléatoire, vous voulez probablement la variante 2 (RFC 4122) et la version 4, auquel cas 6 certains bits doivent être définis sur les bonnes valeurs.
jtpereyda
1
Oui, @dafrazzman a raison. Le fait de rassembler au hasard quelque chose qui "ressemble à un UUID" ne garantit pas l'unicité. Bien qu'aucun UUID ne soit vraiment garanti, en construire un avec des nombres aléatoires est de loin plus vulnérable aux collisions et ne pourrait pas être digne de l'étiquette "UUID". Allez certainement avec SecureRandom.uuid!
dooleyo le

Réponses:

312

Depuis Ruby 1.9, la génération uuid est intégrée. Utilisez la SecureRandom.uuidfonction.

Par exemple:

require 'securerandom'
SecureRandom.uuid # => "96b0a57c-d9ae-453f-b56f-3b154eb10cda"
J _
la source
5
SecureRandom.uuid génère un UUID aléatoire, il n'est donc pas garanti comme unique. Si vous voulez juste une chaîne aléatoire qui est probablement unique, vous pouvez l'utiliser. Cependant, si vous voulez quelque chose qui est garanti pour être unique, vous devrez utiliser quelque chose qui inclut l'adresse MAC, l'horodatage, etc.
Mike Dotterer
23
Pour vous épargner un peu de recherche, vous aurez besoin de 'securerandom'
Jesse Shieh
8
Il n'est pas garanti que ce soit unique, mais pour la plupart des raisons pratiques, on peut supposer qu'il est unique. Voir: stackoverflow.com/questions/2977593/…
Jesse Shieh
si SecureRandom.uuid suit la RFC 4122 comme indiqué dans la documentation, cela ne signifie-t-il pas qu'il a un champ d'horodatage? À l'exception de la concurrence, cela ne signifie-t-il pas unique?
Michael K Madison
@MichaelKMadison AFAIK Ruby utilise la variante "v4" de la RFC 4122, qui n'utilise pas d'horodatage, donc le risque de collision n'est pas réellement nul - mais en pratique il peut l'être aussi
Edd Morgan
38

Comment créer de petits jetons uniques en Ruby

>> require 'digest'
=> []
>> Digest::SHA1.hexdigest("some-random-string")[8..16]
=> "2ebe5597f"

>> SecureRandom.base64(8).gsub("/","_").gsub(/=+$/,"")
=> "AEWQyovNFo0" 

>> rand(36**8).to_s(36)
=> "uur0cj2h"
Simone Carletti
la source
35

Nous utilisons UUIDTools et n'avons aucun problème avec cela.

Avdi
la source
2
«uuidtools» fonctionne, même lorsque le système n'a pas d'adresse MAC. «uuid» échoue dans ce cas.
grefab
3
Contrairement au gem uuid, uuidtools ne conserve aucun fichier d'état. Les problèmes de permission avec le fichier d'état rendent le gem uuid quelque peu difficile à utiliser avec plusieurs utilisateurs.
Wayne Conrad
1
Il semble que les outils UUID ne sont plus maintenus. Il n'y a eu aucun engagement dans le repo github depuis plus de 2 ans
Sudhanshu Mishra
22

Avez-vous regardé UUIDTools ?

UUIDTools a été conçu pour être une bibliothèque simple pour générer l'un des différents types d'UUID (ou GUID si vous préférez les appeler ainsi). Il est conforme à la RFC 4122 dans la mesure du possible.

Andrew Hare
la source
16

Google produit la bibliothèque Ruby suivante:

http://raa.ruby-lang.org/project/ruby-guid/

De plus, sur http://www.ruby-forum.com/topic/99262, ils disent que vous pouvez installer un gem (exécutez gem uuidsur la ligne de commande pour l'installer), puis faites

gem 'uuid'
puts UUID.new

dans votre code pour voir un nouvel UUID.

(Indice: j'ai recherché guid ruby ​​sur Google )

Marc W
la source
thx j'ai vu ça mais c'est super vieux, je cherche juste quelque chose d'actif, comme un bijou récent?
Lance Pollard
Que diriez-vous de la gemme uuid que j'ai ajoutée à ma réponse? Ou est-ce celui dont vous parliez?
Marc W
5
C'est étrange ... J'ai également recherché sur Google "guid ruby", et tout ce que j'ai eu, c'est ce message SO :-P
Jason Whitehorn
3

Pour créer un GUID mysql, varchar 32 approprié

SecureRandom.uuid.gsub('-','').upcase
Aaron Henderson
la source
OuSecureRandom.hex.upcase
Daniel Antonio Nuñez Carhuayo
3

Petite mise à jour de la réponse de Simone Carletti:

SecureRandom.base64 (8) .gsub ("/", "_"). Gsub (/ = + $ /, "")

=> "AEWQyovNFo0"

peut être remplacé par:

SecureRandom.urlsafe_base64 (8)

Алексей Лещук
la source
1

En programmant tard dans la nuit, j'ai proposé la solution suivante (basée sur Simone) pour générer un GUID unique dans Rails. Je n'en suis pas fier mais cela fonctionne assez bien.

while Order.find_by_guid(guid = rand(36**8).to_s(36).upcase).present?; end
robot peut
la source
2
J'espère que vous vous êtes souvenu d'indexer votre colonne guid ce soir
Nurettin
0

Lorsque j'ai utilisé les gemmes uuid recommandées dans cette question, personne ne peut générer un UUID unique et aléatoire. Ma réponse est un travail autour, si nous avons plus tard des gemmes pour satisfaire la demande, vous feriez mieux d'utiliser des gemmes en Ruby.

J'essaie les gemmes uuid les plus recommandées dans cette question, mais personne ne me satisfait, nous avons besoin d'un uuid unique et aléatoire. J'exécute directement la commande système uuidgendans ruby, et j'aime le résultat, et je partage ici.

puts `uuidgen`
8adea17d-b918-43e0-b82f-f81b3029f688
puts `uuidgen`
6a4adcce-8f64-41eb-bd7e-e65ee6d11231
puts `uuidgen`
51d5348b-8fc3-4c44-a6f7-9a8588d7f08a
puts `uuidgen`
332a0fa3-7b07-41e1-9fc8-ef804a377e4e

si vous comparez avec un uuidbijou, vous saurez la différence.

irb(main):003:0> uuid.generate
=> "40cdf890-ebf5-0132-2250-20c9d088be77"
irb(main):004:0> uuid.generate
=> "4161ac40-ebf5-0132-2250-20c9d088be77"

L'environnement de test est l'environnement Linux et Mac OS.

BMW
la source
2
a puts `...`fait essentiellement un appel système uuidgen(3)qui échoue sur toute autre plate-forme autre que Linux, ajoute des temps d'exécution extrêmes et, en général, est une pratique de codage vraiment contre-intuitive. Pourquoi choisiriez-vous une telle méthode?
Dwight Spencer
1
@DwightSpencer Je pense que nous sommes dans un domaine différent avec des objectifs différents. Ce qui vous importe n'est pas du tout dans mes préoccupations, comme le temps d'exécution, le large éventail de systèmes d'exploitation, les migrations de code. Je me soucie que le code puisse fonctionner sous Mac OS ou Linux principal et obtenir le bon résultat dont j'ai besoin. Bien sûr, si vous pouvez trouver un moyen dans Ruby et obtenir le même résultat que la commande uuidgen, je suis heureux de l'utiliser. Mais jusqu'à présent, je n'en ai trouvé aucun.
BMW
1
@J_ et @ simone-carletti ont déjà indiqué un meilleur moyen sur ce post. Pour ma part, je suggérerais SecureRandomque cela préforme la même fonction dans la même méthode que uuidgenmais contrairement à uuidgenl'utilisation du blocage / dev / random SecureRandomutilise uniquement la bibliothèque d'openssl d'abord, puis passe à dev / urandom puis enfin / dev / random pour tenter de le faire génération de randomisation non bloquante.
Dwight Spencer
0

C'est une technique de neet que j'ai apprise de JavaScript:

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[rand(36)]
    end
end

Bien que d'une manière plus `` rubis '', on puisse également faire:

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        rand(16).to_s(16)
    end
end
Sancarn
la source