RubyでのGUIDの生成


142

Guidsで本当に簡単に解決できる問題があります。

特に、パスワードリセットワークフローの場合、Guidトークンをユーザーのメールに送信し、トークンを使用してパスワードをリセットしてもらいます。GUIDは一意であるため、これはかなり安全であり、パスワードをメールで送信する手間が省けます。これは危険です。

Ruby には1つのGuid gemがあることに気づきました。しかし、かなり古く見え、ファイルシステムにデータを書き込みます。

グローバルに一意の識別子を作成できる他の宝石を知っている人はいますか?

私はフォールバックできることを知っています:

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

しかし、実際には適切なGUIDのようには見えません...


1
このようなランダムな文字列を使用することは、正しくありません。UUIDの特定のビットは、バリアントとバージョンを指定します。ランダムなUUIDの場合、おそらくバリアント2(RFC 4122)とバージョン4が必要です。この場合、6つの特定のビットを正しい値に設定する必要があります。
jtpereyda 2013

1
はい、@ dafrazzmanは正しいです。「UUIDに似ている」ものをランダムにつなぎ合わせても、一意性は保証されません。UUIDは真に保証されていませんが、乱数を使ってUUIDを作成すると、衝突の影響を受けやすくなり、「UUID」というラベルにふさわしくありません。間違いなくSecureRandom.uuidを使用してください!
dooleyo 2013

回答:


312

Ruby 1.9以降、uuid生成が組み込まれています。SecureRandom.uuid関数を使用します。

例えば:

require 'securerandom'
SecureRandom.uuid # => "96b0a57c-d9ae-453f-b56f-3b154eb10cda"

5
SecureRandom.uuidはランダムなUUIDを生成するため、一意であるとは限りません。おそらく一意であるランダムな文字列だけが必要な場合は、これを使用してもかまいません。ただし、一意であることが保証されているものが必要な場合は、MACアドレス、タイムスタンプなどを含むものを使用する必要があります。
Mike Dotterer、2012年

23
少しのルックアップを節約するには、「セキュアなランダム性」を要求する必要があります
Jesse Shieh

8
一意であるとは限りませんが、実際には、一意であると想定しても安全です。参照:stackoverflow.com/questions/2977593/...
ジェシーShieh

ドキュメントによると、SecureRandom.uuidがRFC 4122に従っている場合、それはタイムスタンプフィールドがあることを意味しませんか?並行性がなければ、それはユニークなことを意味しませんか?
マイケルKマディソン

@MichaelKMadison AFAIK Rubyは、タイムスタンプを使用しないRFC 4122の「v4」バリアントを使用しているため、衝突の可能性は実際にはゼロではありませんが、実際にはそうなる可能性があります
Edd Morgan


35

私たちはUUIDToolsを使用しており、問題はありません。


2
システムにMACアドレスがない場合でも、「uuidtools」は機能します。この場合、 'uuid'は失敗します。
grefab

3
uuid gemとは異なり、uuidtoolsは状態ファイルを保持しません。状態ファイルのアクセス許可の問題により、uuid gemを複数のユーザーで使用するのが多少面倒になります。
ウェインコンラッド

1
UUIDツールはもうメンテナンスされていないようです。2年以上、
GitHub

22

UUIDToolsを見ましたか?

UUIDToolsは、さまざまなタイプのUUID(またはGUIDを呼び出す場合はGUID)を生成するためのシンプルなライブラリとして設計されています。可能な限りRFC 4122に準拠しています。


16

Googleは次のRubyライブラリを生成します。

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

また、http: //www.ruby-forum.com/topic/99262で、gemをインストールして(gem uuidコマンドラインで実行してインストールする)、次のようにできると言っています

gem 'uuid'
puts UUID.new

コードで新しいUUIDを確認します。

(ヒント:私はguid rubyをGoogleで検索しました


thx私はそれを見ましたが、それは非常に古く、最近の宝石のようなアクティブなものを探しているだけですか?
ランスポラール

回答に追加したuuid gemはどうですか?それとも、あなたが言及していたものですか?
Marc W、

5
それは奇妙なことです...私は「guid ruby​​」もググっていました、そして私が得たすべてはこのSOポストでした:-P
Jason Whitehorn


3

Simone Carlettiの回答の小さな更新:

SecureRandom.base64(8).gsub( "/"、 "_")。gsub(/ = + $ /、 "")

=> "AEWQyovNFo0"

と置き換えることができます:

SecureRandom.urlsafe_base64(8)


1

深夜のプログラミング中に、Railsで一意のGUIDを生成するための次のソリューション(Simoneに基づく)を思いつきました。私はそれを誇りに思っていませんが、それはかなりうまくいきます。

while Order.find_by_guid(guid = rand(36**8).to_s(36).upcase).present?; end

2
その夜、あなたのguidカラムにインデックスを付けたことを覚えているといいのですが
nurettin 2013

0

この質問で推奨されているuuid gemを使用した場合、一意でランダムなUUIDを生成することはできません。私の答えは回避策です。後で要求を満たすgemがある場合は、Rubyでgemを使用することをお勧めします。

私はこの質問で最も推奨されるuuid宝石を試しますが、誰も私を満足させません。ユニークでランダムなuuidが必要です。私uuidgenはルビーで直接システムコマンドを実行し、その結果が気に入ったので、ここで共有します。

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

uuid宝石と比較すると、違いがわかります。

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

テスト環境はLinuxとMac OS環境です。


2
a puts `...`は基本的にuuidgen(3)、Linux以外のプラットフォームで失敗するシステムコールを実行し、極端な実行時間を追加します。一般に、直感に反するコーディング方法です。なぜあなたはそのような方法を選ぶのですか?
ドワイトスペンサー、

1
@DwightSpencer私たちは別の目的で別のエリアにいると思います。実行時間、さまざまなオペレーティングシステム、コードの移行など、気になっていることはまったく問題ではありません。コードがMac OSまたはメインストリームLinuxで機能し、必要な正しい結果が得られることを気にしています。いい加減に、Rubyで方法を考え出してuuidgenコマンドと同じ結果を得ることができれば、私はそれを使って喜んでいます。しかし、今まで私は何も見つかりませんでした。
BMW

1
@J_と@ simone-carlettiの両方が、この投稿ですでにより良い方法を指摘しています。私は1つが示唆しているためSecureRandomと同じ方法で同じ機能を予備成形されたものとuuidgenが、とは違ってuuidgen、ブロッキングの/ dev /ランダムの使用が唯一のSecureRandom最初のその後のopensslのライブラリを使用すると、最終的には/ dev /ランダム行うための試みで、その後DEV / urandomのに低下し非ブロック化ランダム化生成。
ドワイトスペンサー

0

これは私がJavaScriptから学んだ素晴らしいテクニックです:

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

より「ルビーな方法」で人はそうすることもできましたが:

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        rand(16).to_s(16)
    end
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.