Gerando Guids em Ruby

142

Eu tenho um problema que é realmente facilmente resolvido com o Guids.

Em particular, para um fluxo de trabalho de redefinição de senha, gostaria de enviar um token Guid para o e-mail de um usuário e redefinir sua senha usando o token. Como os guias são exclusivos, isso é bastante seguro e me salva o envio de senhas para as pessoas, o que é arriscado.

Notei que há uma jóia Guid para Ruby; mas parece bastante antigo e grava coisas no sistema de arquivos.

Alguém conhece outras gemas que podem criar um identificador globalmente exclusivo?

Eu sei que posso simplesmente voltar a:

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

Mas realmente não parece um GUID adequado ...

Sam Saffron
fonte
1
Usar uma string aleatória como essa não seria correto; certos bits no UUID especificam variante e versão. Para um UUID aleatório, você provavelmente deseja a variante 2 (RFC 4122) e a versão 4; nesse caso, 6 bits determinados devem ser definidos com os valores corretos.
Jtpereyda
1
Sim @dafrazzman está certo. Montar aleatoriamente algo que "se assemelha a um UUID" não garante exclusividade. Embora nenhum UUID seja realmente garantido, a criação de um com números aleatórios é MUITO mais suscetível a colisões e não pode ser digna do rótulo "UUID". Definitivamente vá com SecureRandom.uuid!
Dooleyo

Respostas:

312

A partir do Ruby 1.9, a geração de uuid é incorporada. Use a SecureRandom.uuidfunção

Por exemplo:

require 'securerandom'
SecureRandom.uuid # => "96b0a57c-d9ae-453f-b56f-3b154eb10cda"
J _
fonte
5
SecureRandom.uuid gera um UUID aleatório, portanto não é garantido como único. Se você quiser apenas uma sequência aleatória provavelmente única, não há problema em usá-la. No entanto, se você quiser algo que é garantido como único, precisará usar algo que inclua o endereço MAC, o carimbo de data e hora e etc.
Mike Dotterer
23
Para poupar-lhe um pouco de pesquisa, você vai precisar para exigir 'SecureRandom'
Jesse Shieh
8
Não é garantido que seja único, mas, para fins mais práticos, é seguro assumir que é único. Veja: stackoverflow.com/questions/2977593/…
Jesse Shieh
se o SecureRandom.uuid seguir a RFC 4122, conforme indicado na documentação, isso não significa que ele possui um campo de carimbo de data / hora? Exceto a concorrência, isso não significa único?
Michael K Madison
@MichaelKMadison AFAIK Ruby usa a variante "v4" do RFC 4122, que não usa um timestamp, então a chance de colisão não é realmente zero - mas na prática pode muito bem ser
Edd Morgan
38

Como criar pequenos tokens exclusivos em 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
fonte
35

Usamos UUIDTools e não temos problemas com isso.

Avdi
fonte
2
'uuidtools' funciona, mesmo quando o sistema não possui endereço MAC. 'uuid' falha neste caso.
grefab 20/09/10
3
Ao contrário da gema uuid, o uuidtools não mantém nenhum arquivo de estado. Os problemas de permissão com o arquivo de estado tornam a gem uuid um pouco difícil de usar com vários usuários.
Wayne Conrad
1
Parece que o UUID Tools não é mais mantido. Não há nenhum compromisso com o repositório github há mais de 2 anos
Sudhanshu Mishra
22

Você olhou para o UUIDTools ?

O UUIDTools foi projetado para ser uma biblioteca simples para gerar qualquer um dos vários tipos de UUIDs (ou GUIDs, se você preferir chamá-los assim). Está em conformidade com a RFC 4122 sempre que possível.

Andrew Hare
fonte
16

O Google produz a seguinte biblioteca Ruby:

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

Além disso, em http://www.ruby-forum.com/topic/99262, eles dizem que você pode instalar uma gema (execute gem uuidna linha de comando para instalá-la) e depois

gem 'uuid'
puts UUID.new

no seu código para ver um novo UUID.

(Dica: eu pesquisei no Google por ruby guid )

Marc W
fonte
thx eu vi isso, mas é super antigo, apenas procurando por algo ativo, como uma jóia recente?
Lance Pollard
Que tal a gema uuid que eu adicionei à minha resposta? Ou é aquele a quem você estava se referindo?
Marc W
5
Isso é estranho ... eu pesquisei no google "guid ruby" também, e tudo que consegui foi este post do SO :-P
Jason Whitehorn
3

Para criar um GUID adequado, mysql, varchar 32

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

Pequena atualização para Simone Carletti resposta:

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

=> "AEWQyovNFo0"

pode ser substituído por:

SecureRandom.urlsafe_base64 (8)

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

Enquanto programava tarde da noite, criei a seguinte solução (baseada na Simone) para gerar um GUID exclusivo no Rails. Não tenho orgulho disso, mas funciona muito bem.

while Order.find_by_guid(guid = rand(36**8).to_s(36).upcase).present?; end
robotmay
fonte
2
Eu espero que você se lembrou de indexar o seu coluna guid naquela noite
nurettin
0

Quando usei gemas uuid recomendadas nesta pergunta, ninguém pode gerar UUID exclusivo e aleatório. Minha resposta é uma solução alternativa: se tivermos gemas posteriormente para atender à solicitação, é melhor usar gemas no Ruby.

Eu tento as gemas uuid mais recomendadas nesta questão, mas ninguém me deixa satisfeito, precisamos de uma uuid única e aleatória. Eu corro diretamente o comando do sistema uuidgenem ruby, gosto do resultado e compartilho aqui.

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

se comparar com a uuidgema, você saberá a diferença.

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

O ambiente de teste é Linux e Mac OS.

BMW
fonte
2
a puts `...`é basicamente fazer uma chamada de sistema à uuidgen(3)qual falha em qualquer outra plataforma que não seja o Linux, adiciona quantidades extremas de tempo de execução e, em geral, é realmente uma prática de codificação contra-intuitiva. Por que você escolheria esse método?
Dwight Spencer
1
@DwightSpencer Acho que estamos em uma área diferente com propósitos diferentes. O que você se importa não está em minhas preocupações, como o tempo de execução, a ampla gama de sistemas operacionais, as migrações de código. Eu me importo que o código possa funcionar no Mac OS ou no fluxo principal do Linux e obtenha o resultado certo de que preciso. É claro que, se você consegue descobrir uma maneira em Ruby e obter o mesmo resultado que o comando uuidgen, fico feliz em usá-lo. Mas até agora, eu não encontrei nenhum.
BMW
1
@J_ e @ simone-carletti já apontaram uma maneira melhor neste post. Eu, pelo menos, sugeriria SecureRandomque isso está pré-formando a mesma função no mesmo método, uuidgenmas, ao contrário uuidgendo uso do bloqueio / dev / random, ele SecureRandomusa apenas a biblioteca do openssl primeiro e depois cai para dev / urandom e, finalmente, / dev / random na tentativa de fazer geração de randomização sem bloqueio.
Dwight Spencer
0

Esta é uma técnica neet que aprendi com JavaScript:

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

Embora de uma forma mais "rubi", também se possa fazer:

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