Menghasilkan Panduan di Ruby

142

Saya memiliki masalah yang sangat mudah diselesaikan dengan Panduan.

Khususnya, untuk alur kerja pengaturan ulang kata sandi, saya ingin mengirim token Guid ke email pengguna dan meminta mereka mengatur ulang kata sandi mereka menggunakan token. Karena petunjuk unik, ini cukup aman dan menyelamatkan saya mengirim email kata sandi orang, yang berisiko.

Saya perhatikan ada satu permata Guid untuk Ruby; tetapi terlihat cukup tua, dan ia menulis hal-hal ke sistem file.

Adakah yang tahu tentang permata lain yang dapat membuat pengidentifikasi unik secara global?

Saya tahu saya bisa kembali ke:

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

Tapi itu tidak benar-benar tampak seperti GUID yang tepat ...

Sam Saffron
sumber
1
Menggunakan string acak seperti itu tidak akan tepat; bit tertentu dalam UUID menentukan varian dan versi. Untuk UUID acak, Anda mungkin menginginkan varian 2 (RFC 4122) dan versi 4, dalam hal ini 6 bit tertentu harus disetel ke nilai yang benar.
jtpereyda
1
Ya @ dafrazzman benar. Secara acak menyatukan sesuatu yang "menyerupai UUID" tidak menjamin keunikan. Meskipun tidak ada UUID yang benar - benar dijamin, membangun satu dengan nomor acak JAUH lebih rentan terhadap tabrakan dan tidak layak label "UUID". Jelas pergi dengan SecureRandom.uuid!
dooleyo

Jawaban:

312

Pada Ruby 1.9, generasi uuid sudah terintegrasi. Gunakan SecureRandom.uuidfungsinya.

Sebagai contoh:

require 'securerandom'
SecureRandom.uuid # => "96b0a57c-d9ae-453f-b56f-3b154eb10cda"
J _
sumber
5
SecureRandom.uuid menghasilkan UUID acak, sehingga tidak dijamin unik. Jika Anda hanya menginginkan string acak yang mungkin unik, boleh saja menggunakan ini. Namun, jika Anda menginginkan sesuatu yang dijamin unik, Anda perlu menggunakan sesuatu yang mencakup alamat MAC, timestamp, dan lain-lain.
Mike Dotterer
23
Untuk menghemat sedikit pencarian, Anda harus meminta 'securerandom'
Jesse Shieh
8
Ini tidak dijamin unik, tetapi untuk sebagian besar tujuan praktis, aman untuk menganggapnya unik. Lihat: stackoverflow.com/questions/2977593/…
Jesse Shieh
jika SecureRandom.uuid ikuti RFC 4122 seperti yang dikatakan sesuai dengan dokumentasi, bukankah itu berarti ia memiliki bidang cap waktu? Kecuali konkurensi, bukankah itu berarti unik?
Michael K Madison
@MichaelKMadison AFAIK Ruby menggunakan varian "v4" dari RFC 4122, yang tidak menggunakan stempel waktu, jadi kemungkinan tabrakan sebenarnya tidak nol - tetapi dalam praktiknya mungkin juga
Edd Morgan
38

Cara membuat token kecil dan unik di 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
sumber
35

Kami menggunakan UUIDTools dan tidak memiliki masalah dengannya.

Avdi
sumber
2
'uuidtools' berfungsi, bahkan ketika sistem tidak memiliki alamat MAC. 'uuid' gagal dalam kasus ini.
grefab
3
Tidak seperti gem uuid, uuidtools tidak menyimpan file status. Masalah izin dengan file status membuat permata uuid agak canggung untuk digunakan dengan banyak pengguna.
Wayne Conrad
1
Tampaknya Alat UUID tidak dipertahankan lagi. Belum ada komitmen untuk repo github dalam lebih dari 2 tahun
Sudhanshu Mishra
22

Apakah Anda melihat UUIDTools ?

UUIDTools dirancang untuk menjadi perpustakaan sederhana untuk menghasilkan berbagai jenis UUID (atau GUID jika Anda lebih suka menyebutnya demikian). Ini sesuai dengan RFC 4122 bila memungkinkan.

Andrew Hare
sumber
16

Google menghasilkan pustaka Ruby berikut:

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

Juga, di http://www.ruby-forum.com/topic/99262 mereka mengatakan Anda dapat menginstal permata (jalankan gem uuidpada baris perintah untuk menginstalnya) dan kemudian lakukan

gem 'uuid'
puts UUID.new

dalam kode Anda untuk melihat UUID baru.

(Petunjuk: I Googled untuk ruby panduan )

Marc W
sumber
Terima kasih, tapi itu super tua, hanya mencari sesuatu yang aktif, seperti permata baru-baru ini?
Lance Pollard
Bagaimana dengan permata uuid yang saya tambahkan ke jawaban saya? Atau apakah itu yang Anda maksud?
Marc W
5
Itu aneh ... Saya juga mencari "ruby pedoman" di Google, dan yang saya dapatkan hanyalah pos SO ini :-P
Jason Whitehorn
3

Untuk membuat yang benar, mysql, varchar 32 GUID

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

Pembaruan kecil untuk jawaban Simone Carletti:

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

=> "AEWQyovNFo0"

dapat diganti dengan:

SecureRandom.urlsafe_base64 (8)

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

Saat pemrograman larut malam saya datang dengan solusi berikut (berdasarkan dari Simone) untuk menghasilkan GUID unik di Rails. Saya tidak bangga akan hal itu tetapi itu bekerja dengan cukup baik.

while Order.find_by_guid(guid = rand(36**8).to_s(36).upcase).present?; end
robotmay
sumber
2
Saya harap Anda ingat untuk mengindeks kolom panduan Anda malam itu
nurettin
0

Ketika saya menggunakan permata uuid yang direkomendasikan dalam pertanyaan ini, tidak ada yang dapat menghasilkan UUID unik dan acak. Jawaban saya adalah solusi, jika kami memiliki permata nanti untuk memenuhi permintaan, Anda sebaiknya menggunakan permata di Ruby.

Saya mencoba permata uuid yang paling direkomendasikan dalam pertanyaan ini, tetapi tidak ada yang membuat saya puas, kita perlu uuid unik dan acak. Saya langsung menjalankan perintah sistem uuidgendi ruby, dan saya suka hasilnya, dan berbagi di sini.

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

jika dibandingkan dengan uuidpermata, Anda akan tahu bedanya.

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

Lingkungan pengujian adalah lingkungan linux dan Mac OS.

BMW
sumber
2
a puts `...`pada dasarnya melakukan panggilan sistem uuidgen(3)yang gagal pada platform lain selain Linux, menambah jumlah waktu eksekusi yang ekstrem, dan secara umum benar-benar bertentangan dengan praktik pengkodean intuitif. Mengapa Anda memilih metode seperti itu?
Dwight Spencer
1
@DwightSpencer Saya pikir kami berada di area yang berbeda dengan tujuan yang berbeda. Apa yang Anda pedulikan tidak menjadi perhatian saya sama sekali, seperti waktu eksekusi, berbagai sistem operasi, migrasi kode. Saya peduli kodenya dapat bekerja di Mac OS atau aliran utama Linux dan mendapatkan hasil yang tepat yang saya butuhkan. Tentu saja, jika Anda bisa mencari cara di Ruby dan mendapatkan hasil yang sama dengan perintah uuidgen, saya senang menggunakannya. Tetapi sampai sekarang, saya tidak menemukannya.
BMW
1
@J_ dan @ simone-carletti telah menunjukkan cara yang lebih baik pada posting ini. I untuk satu akan menyarankan SecureRandomkarena yang membentuk fungsi yang sama dalam metode yang sama seperti uuidgentetapi tidak seperti uuidgenpenggunaan pemblokiran / dev / acak hanya SecureRandommenggunakan perpustakaan openssl pertama kemudian turun ke dev / urandom kemudian akhirnya / dev / acak dalam upaya untuk melakukan generasi pengacakan tidak menghalangi.
Dwight Spencer
0

Ini adalah teknik neet yang saya pelajari dari JavaScript:

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

Meskipun dengan cara yang lebih 'ruby' seseorang juga bisa melakukannya:

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