Generieren von Guids in Ruby

142

Ich habe ein Problem, das mit Guids wirklich leicht zu lösen ist.

Insbesondere für einen Workflow zum Zurücksetzen von Passwörtern möchte ich ein Guid-Token an die E-Mail-Adresse eines Benutzers senden und ihn sein Passwort mithilfe des Tokens zurücksetzen lassen. Da Guids einzigartig sind, ist dies ziemlich sicher und erspart mir das Versenden von Passwörtern per E-Mail, was riskant ist.

Mir ist aufgefallen, dass es einen Guid-Edelstein für Ruby gibt. aber es sieht ziemlich alt aus und schreibt Sachen in das Dateisystem.

Kennt jemand andere Edelsteine, die eine global eindeutige Kennung erstellen können?

Ich weiß, ich kann einfach zurückgreifen auf:

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

Aber es scheint nicht wirklich eine richtige GUID zu sein ...

Sam Safran
quelle
1
Die Verwendung einer solchen zufälligen Zeichenfolge wäre nicht ganz richtig. Bestimmte Bits in der UUID geben Variante und Version an. Für eine zufällige UUID möchten Sie wahrscheinlich Variante 2 (RFC 4122) und Version 4, in welchem ​​Fall 6 bestimmte Bits auf die richtigen Werte gesetzt werden müssen.
jtpereyda
1
Ja, @dafrazzman ist richtig. Das zufällige Zusammensetzen von etwas, das "einer UUID ähnelt", garantiert keine Eindeutigkeit. Während keine UUID wirklich garantiert ist, ist das Erstellen einer UUID mit Zufallszahlen weitaus anfälliger für Kollisionen und könnte das Label "UUID" nicht verdienen. Gehen Sie auf jeden Fall mit SecureRandom.uuid!
Dooleyo

Antworten:

312

Ab Ruby 1.9 ist die UUID-Generierung integriert. Verwenden Sie die SecureRandom.uuidFunktion.

Beispielsweise:

require 'securerandom'
SecureRandom.uuid # => "96b0a57c-d9ae-453f-b56f-3b154eb10cda"
J _
quelle
5
SecureRandom.uuid generiert eine zufällige UUID, sodass nicht garantiert wird, dass sie eindeutig ist. Wenn Sie nur eine zufällige Zeichenfolge möchten, die wahrscheinlich eindeutig ist, können Sie diese verwenden. Wenn Sie jedoch etwas möchten, das garantiert eindeutig ist, müssen Sie etwas verwenden, das die MAC-Adresse, den Zeitstempel usw. enthält.
Mike Dotterer
23
Um Ihnen ein bisschen Nachschlagen zu ersparen, müssen Sie 'securerandom' benötigen
Jesse Shieh
8
Es ist nicht garantiert, dass es einzigartig ist, aber für die meisten praktischen Zwecke kann man davon ausgehen, dass es einzigartig ist. Siehe: stackoverflow.com/questions/2977593/…
Jesse Shieh
Wenn SecureRandom.uuid RFC 4122 folgt, wie in der Dokumentation angegeben, bedeutet dies nicht, dass es ein Zeitstempelfeld hat? Bedeutet das, abgesehen von Parallelität, nicht einzigartig?
Michael K Madison
@MichaelKMadison AFAIK Ruby verwendet die "v4" -Variante von RFC 4122, die keinen Zeitstempel verwendet, so dass die Wahrscheinlichkeit einer Kollision nicht gleich Null ist - in der Praxis kann es aber auch sein
Edd Morgan
38

So erstellen Sie kleine, einzigartige Token in 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
quelle
35

Wir verwenden UUIDTools und haben keine Probleme damit.

Avdi
quelle
2
'uuidtools' funktioniert auch dann, wenn das System keine MAC-Adresse hat. 'uuid' schlägt in diesem Fall fehl.
Grefab
3
Im Gegensatz zum uuid-Juwel speichert uuidtools keine Statusdatei. Berechtigungsprobleme mit der Statusdatei machen die Verwendung des UUID-Edelsteins für mehrere Benutzer etwas umständlich.
Wayne Conrad
1
Es scheint, dass UUID Tools nicht mehr gepflegt werden. Es gab seit über 2 Jahren keine Verpflichtung mehr für das Github-Repo
Sudhanshu Mishra
22

Hast du dir UUIDTools angesehen ?

UUIDTools wurde als einfache Bibliothek zum Generieren einer der verschiedenen Arten von UUIDs (oder GUIDs, wenn Sie sie lieber so nennen möchten) entwickelt. Es entspricht nach Möglichkeit RFC 4122.

Andrew Hare
quelle
16

Google liefert die folgende Ruby-Bibliothek:

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

Außerdem sagen sie unter http://www.ruby-forum.com/topic/99262 , dass Sie ein Juwel installieren können ( gem uuidin der Befehlszeile ausführen , um es zu installieren) und dann tun

gem 'uuid'
puts UUID.new

in Ihrem Code, um eine neue UUID zu sehen.

(Hinweis: Ich habe nach Guid Ruby gegoogelt )

Marc W.
quelle
thx ich habe das gesehen, aber es ist super alt, nur auf der Suche nach etwas Aktivem, wie einem neuen Juwel?
Lance Pollard
Wie wäre es mit dem Edelstein, den ich meiner Antwort hinzugefügt habe? Oder ist das derjenige, auf den Sie sich bezogen haben?
Marc W
5
Das ist seltsam ... Ich habe auch "guid ruby" gegoogelt und alles, was ich bekam, war dieser SO-Beitrag :-P
Jason Whitehorn
3

Um eine richtige, mysql, varchar 32 GUID zu erstellen

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

Kleines Update zu Simone Carletti Antwort:

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

=> "AEWQyovNFo0"

kann ersetzt werden durch:

SecureRandom.urlsafe_base64 (8)

Алексей Лещук
quelle
1

Während ich spät abends programmierte, kam ich auf die folgende Lösung (basierend auf Simones), um eine eindeutige GUID in Rails zu generieren. Ich bin nicht stolz darauf, aber es funktioniert ganz gut.

while Order.find_by_guid(guid = rand(36**8).to_s(36).upcase).present?; end
Roboter kann
quelle
2
Ich hoffe, Sie haben daran gedacht, Ihre Guid-Kolumne in dieser Nacht zu
indizieren
0

Wenn ich in dieser Frage empfohlene UUID-Edelsteine ​​verwendet habe, kann niemand eine eindeutige und zufällige UUID generieren. Meine Antwort ist eine Problemumgehung. Wenn wir später Edelsteine ​​haben, um die Anfrage zu erfüllen, sollten Sie Edelsteine ​​in Ruby verwenden.

Ich versuche die meisten empfohlenen UUID-Edelsteine ​​in dieser Frage, aber niemand macht mich zufrieden. Wir brauchen eine einzigartige und zufällige UUID. Ich führe den Systembefehl direkt uuidgenin Ruby aus, und das Ergebnis gefällt mir und teile es hier.

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

Wenn Sie mit uuidEdelstein vergleichen , werden Sie den Unterschied kennen.

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

Die Testumgebung ist eine Linux- und Mac OS-Umgebung.

BMW
quelle
2
a puts `...`führt im Grunde genommen einen Systemaufruf durch, uuidgen(3)der auf einer anderen Plattform als Linux fehlschlägt, die Ausführungszeit extrem verlängert und im Allgemeinen der intuitiven Codierungspraxis widerspricht. Warum würden Sie eine solche Methode wählen?
Dwight Spencer
1
@ DwightSpencer Ich denke, wir sind in verschiedenen Bereichen mit unterschiedlichen Zwecken. Was Sie interessiert, ist überhaupt nicht in meinen Anliegen, wie die Ausführungszeit, die breite Palette von Betriebssystemen, Code-Migrationen. Es ist mir wichtig, dass der Code unter Mac OS oder Linux funktioniert und das richtige Ergebnis erzielt, das ich brauche. Natürlich, wenn Sie einen Weg in Ruby finden und das gleiche Ergebnis wie der Befehl uuidgen erzielen können, bin ich glücklich, ihn zu verwenden. Aber bis jetzt habe ich keine gefunden.
BMW
1
Sowohl @J_ als auch @ simone-carletti haben in diesem Beitrag bereits einen besseren Weg aufgezeigt. Ich für meinen Teil würde vorschlagen SecureRandom, dass dies die gleiche Funktion in der gleichen Methode ausführt, uuidgenaber im Gegensatz uuidgenzur Verwendung des Blockierens verwendet / dev / random nur SecureRandomdie Bibliothek von openssl zuerst und fällt dann bei Versuchen zu dev / urandom und schließlich zu / dev / random nicht blockierende Randomisierungsgenerierung.
Dwight Spencer
0

Dies ist eine Neet-Technik, die ich aus JavaScript gelernt habe:

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

Obwohl man eher "rubinrot" sein könnte:

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