การสร้าง Guids ใน Ruby


142

ฉันมีปัญหาที่แก้ไขได้อย่างง่ายดายด้วย Guids

โดยเฉพาะอย่างยิ่งสำหรับเวิร์กโฟลว์การรีเซ็ตรหัสผ่านฉันต้องการส่งโทเค็น Guid ไปยังอีเมลของผู้ใช้และให้พวกเขารีเซ็ตรหัสผ่านโดยใช้โทเค็น เนื่องจาก guids นั้นไม่เหมือนใครมันค่อนข้างปลอดภัยและช่วยให้ฉันส่งอีเมลรหัสผ่านผู้คนซึ่งมีความเสี่ยง

ฉันสังเกตเห็นว่ามีอัญมณีแห่งหนึ่งสำหรับทับทิม; แต่มันดูค่อนข้างเก่าและเขียนสิ่งต่าง ๆ ลงในระบบไฟล์

ไม่มีใครรู้อัญมณีอื่น ๆ ที่สามารถสร้างตัวระบุที่ไม่ซ้ำกันทั่วโลกได้หรือไม่?

ฉันรู้ว่าฉันสามารถถอยกลับไปที่:

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

แต่ดูเหมือนว่าจะไม่ใช่ GUID ที่เหมาะสมจริง ๆ ...


1
การใช้สตริงแบบสุ่มอย่างนั้นจะไม่ถูกต้องนัก บิตบางตัวใน UUID ระบุชุดตัวเลือกและรุ่น สำหรับ UUID แบบสุ่มคุณอาจต้องการตัวแปร 2 (RFC 4122) และรุ่น 4 ซึ่งในกรณีนี้ 6 บิตที่แน่นอนจะต้องตั้งค่าที่ถูกต้อง
jtpereyda

1
ใช่ @dafrazzman ถูกต้อง การสุ่มประกอบสิ่งที่ "คล้ายกับ UUID" ไม่รับประกันความเป็นเอกลักษณ์ ในขณะที่ไม่มีการรับประกันUUID จริง ๆการสร้างสิ่งที่มีตัวเลขสุ่มจะมีความเสี่ยงต่อการชนกันมากขึ้นและไม่สามารถคู่ควรกับฉลาก "UUID" ไปอย่างแน่นอนกับ SecureRandom.uuid!
dooleyo

คำตอบ:


312

ตั้งแต่ Ruby 1.9 รุ่น uuid นั้นมีมาให้แล้ว ใช้SecureRandom.uuidฟังก์ชั่น

ตัวอย่างเช่น:

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

5
SecureRandom.uuid สร้าง UUID แบบสุ่มดังนั้นจึงไม่รับประกันว่าจะไม่ซ้ำกัน หากคุณเพียงแค่ต้องการสตริงสุ่มที่อาจไม่ซ้ำกันมันจะโอเคที่จะใช้มัน อย่างไรก็ตามหากคุณต้องการสิ่งที่รับประกันว่าไม่เหมือนใครคุณจะต้องใช้สิ่งที่มีที่อยู่ MAC, การประทับเวลาและอื่น ๆ
Mike Dotterer

23
เพื่อประหยัดการค้นหาเล็กน้อยคุณจะต้องมี 'securerandom'
Jesse Shieh

8
มันไม่ได้รับประกันว่าจะไม่ซ้ำกัน แต่เพื่อวัตถุประสงค์ในทางปฏิบัติส่วนใหญ่จะปลอดภัยที่จะถือว่าเป็นเอกลักษณ์ ดู: stackoverflow.com/questions/2977593/…
Jesse Shieh

หาก SecureRandom.uuid ปฏิบัติตาม RFC 4122 ตามที่ระบุไว้ตามเอกสารประกอบนั่นไม่ได้หมายความว่ามันมีช่องเวลาประทับ การ จำกัด การทำงานพร้อมกันนั้นไม่ได้หมายความว่าไม่เหมือนใครใช่ไหม
Michael K Madison

@MichaelKMadison AFAIK Ruby ใช้ตัวแปร "v4" ของ RFC 4122 ซึ่งไม่ได้ใช้การประทับเวลาดังนั้นโอกาสในการปะทะไม่ได้เป็นจริง - แต่ในทางปฏิบัติมันอาจเป็นเช่นนั้น
Edd Morgan


35

เราใช้UUIDToolsและไม่มีปัญหากับมัน


2
'uuidtools' ทำงานได้แม้ว่าระบบจะไม่มีที่อยู่ MAC 'uuid' ล้มเหลวในกรณีนี้
grefab

3
ซึ่งแตกต่างจากอัญมณี uuid uuidtools เก็บไฟล์สถานะไม่ ปัญหาการอนุญาตกับไฟล์สถานะทำให้ uuid gem ค่อนข้างอึดอัดใจที่จะใช้กับผู้ใช้หลายคน
Wayne Conrad

1
ดูเหมือนว่า UUID Tools จะไม่ได้รับการดูแลอีกต่อไป ยังไม่มีการกระทำใด ๆ กับ repo github ในช่วง 2 ปีที่ผ่านมา
Sudhanshu Mishra

22

คุณดูที่UUIDToolsหรือไม่

UUIDTools ได้รับการออกแบบมาให้เป็นห้องสมุดง่าย ๆ สำหรับการสร้าง UUID ประเภทต่าง ๆ (หรือ GUID ถ้าคุณต้องการเรียกพวกมัน) มันสอดคล้องกับ RFC 4122 เมื่อใดก็ตามที่เป็นไปได้


16

Google ให้ไลบรารี่ Ruby ต่อไปนี้:

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

นอกจากนี้ที่http://www.ruby-forum.com/topic/99262พวกเขาบอกว่าคุณสามารถติดตั้งอัญมณี (รันgem uuidบนบรรทัดคำสั่งเพื่อติดตั้ง) แล้วทำ

gem 'uuid'
puts UUID.new

ในรหัสของคุณเพื่อดู UUID ใหม่

(คำแนะนำ: ฉัน Googled สำหรับguid ruby )


ขอบคุณที่ฉันเห็น แต่มันเก่ามากเพียงแค่มองหาบางสิ่งที่แอคทีฟเหมือนอัญมณีล่าสุด?
Lance Pollard

แล้ว uuid gem ที่ฉันเพิ่มเข้าไปในคำตอบของฉันล่ะ? หรือว่าคนที่คุณอ้างถึง?
Marc W

5
นั่นเป็นเรื่องแปลก ... ฉัน googled "guid ruby" เช่นกันและสิ่งที่ฉันได้รับก็คือโพสต์ SO :-P
Jason Whitehorn


3

การอัพเดทเป็นคำตอบ Simone Carletti เล็กน้อย:

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

=> "AEWQyovNFo0"

สามารถถูกแทนที่ด้วย:

SecureRandom.urlsafe_base64 (8)


1

ในขณะที่การเขียนโปรแกรมตอนดึกฉันได้พบกับวิธีแก้ไขปัญหาต่อไปนี้ (ตาม Simone's) เพื่อสร้าง GUID ที่ไม่เหมือนใครใน Rails ฉันไม่ได้ภูมิใจในมัน แต่ทำงานได้ค่อนข้างดี

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

2
ฉันหวังว่าคุณจำได้ว่าจะจัดทำดัชนี guid ของคุณในคืนนั้น
นูเรตต์

0

เมื่อฉันใช้ uuid gems ที่แนะนำในคำถามนี้ไม่มีใครสามารถสร้าง UUID ที่ไม่ซ้ำใครและสุ่ม คำตอบของฉันคือการแก้ไขหากเรามีอัญมณีในภายหลังเพื่อตอบสนองคำขอคุณควรที่จะใช้อัญมณีใน Ruby

ฉันลองอัญมณี 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 เพิ่มเวลาดำเนินการจำนวนมากและโดยทั่วไปเป็นการตอบโต้การเข้ารหัสที่ใช้งานง่าย ทำไมคุณถึงเลือกวิธีดังกล่าว?
Dwight Spencer

1
@DwightSpencer ฉันคิดว่าเราอยู่ในพื้นที่ที่แตกต่างกันโดยมีวัตถุประสงค์ที่แตกต่างกัน สิ่งที่คุณสนใจไม่ได้อยู่ในความกังวลของฉันเลยเช่นเวลาดำเนินการระบบปฏิบัติการที่หลากหลายการโยกย้ายรหัส ฉันดูแลรหัสสามารถทำงานใน Mac OS หรือกระแสหลัก Linux และได้รับผลลัพธ์ที่ถูกต้องที่ฉันต้องการ แน่นอนถ้าคุณสามารถหาวิธีใน Ruby และได้ผลลัพธ์เหมือนกับคำสั่ง uuidgen ฉันยินดีที่จะใช้มัน แต่จนถึงตอนนี้ฉันไม่พบอะไรเลย
BMW

1
ทั้ง @J_ และ @ simone-carletti ได้ชี้แจงวิธีที่ดีกว่าสำหรับโพสต์นี้แล้ว ฉันขอแนะนำอย่างหนึ่งSecureRandomว่านั่นคือ preforming ฟังก์ชั่นเดียวกันในวิธีการเดียวกันuuidgenแต่แตกต่างจากการuuidgenใช้งานของการปิดกั้น / dev / สุ่มSecureRandomใช้ห้องสมุดของ openssl ก่อนแล้วจึงลดลงเป็น dev / urandom แล้วในที่สุด / dev / สุ่มในความพยายามที่จะทำ การสร้างการสุ่มแบบไม่มีการบล็อก
Dwight Spencer

0

นี่เป็นเทคนิค neet ที่ฉันเรียนรู้จาก 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.