Oto, czego używam. Token niekoniecznie musi zostać usłyszany, aby odgadnąć, bardziej przypomina krótki identyfikator adresu URL niż cokolwiek innego i chcę, aby był krótki. I już po kilka przykładów znalazłem w Internecie oraz w razie kolizji, myślę, że kod poniżej będzie odtworzyć token, ale nie jestem pewien rzeczywistym. Jestem jednak ciekawy, aby zobaczyć lepsze sugestie, ponieważ wydaje się to trochę szorstkie na krawędziach.
def self.create_token
random_number = SecureRandom.hex(3)
"1X#{random_number}"
while Tracker.find_by_token("1X#{random_number}") != nil
random_number = SecureRandom.hex(3)
"1X#{random_number}"
end
"1X#{random_number}"
end
Moja kolumna bazy danych dla tokena to unikalny indeks i używam go również validates_uniqueness_of :token
na modelu, ale ponieważ są one tworzone automatycznie partiami na podstawie działań użytkownika w aplikacji (zasadniczo składają zamówienie i kupują tokeny), nie jest możliwe, aby aplikacja zgłosiła błąd.
Mógłbym też, jak sądzę, zmniejszyć ryzyko kolizji, dołączyć na końcu kolejny ciąg, coś wygenerowanego na podstawie czasu lub coś w tym rodzaju, ale nie chcę, aby token był zbyt długi.
źródło
loop do
(pętla typu „while ... do”) powinna być używana w tym przypadku (gdzie pętla jest wymagana do uruchomienia przynajmniej raz) zamiastbegin...while
(pętla typu „do ... while”)?ModelName
tej metody? Może zamiast tego zamienić naself.class
? W przeciwnym razie nie nadaje się do wielokrotnego użytku, prawda?Ryan Bates używa niezłego fragmentu kodu w swoim Railscast na zaproszeniach do bety . Daje to 40-znakowy ciąg alfanumeryczny.
źródło
Digest::SHA1.hexdigest([Time.now, rand].join)[0..10]
hexdigest
danego adresu IP.Może to być późna odpowiedź, ale aby uniknąć używania pętli, możesz również wywołać metodę rekurencyjnie. Wygląda i wydaje mi się nieco czystszy.
źródło
W tym artykule przedstawiono kilka całkiem sprytnych sposobów:
https://web.archive.org/web/20121026000606/http://blog.logeek.fr/2009/7/2/creating-small-unique-tokens-in-ruby
Moja ulubiona lista to:
źródło
if self.new_record? and self.access_token.nil?
... czy to właśnie sprawdza, czy token nie jest już przechowywany?validates_uniqueness_of :token
i dodaj unikalny indeks do tabeli z migracją.Jeśli chcesz czegoś, co będzie wyjątkowe, możesz użyć czegoś takiego:
jednakże spowoduje to wygenerowanie ciągu 32 znaków.
Jest jednak inny sposób:
na przykład dla id, takiego jak 10000, wygenerowany token miałby postać „MTAwMDA =” (i można go łatwo zdekodować dla identyfikatora, wystarczy
źródło
random_string = Digest::MD5.hexdigest("#{ActiveSupport::SecureRandom.hex(10)}-#{DateTime.now.to_s}-#{id}")[1..6]
gdzie ID to identyfikator tokena.Base64::encode64(id.to_s)
sprzeczne z celem używania tokena. Najprawdopodobniej używasz tokena, aby ukryć identyfikator i uniemożliwić dostęp do zasobu każdemu, kto nie ma tego tokena. Jednak w tym przypadku ktoś mógłby po prostu uruchomićBase64::encode64(<insert_id_here>)
i natychmiast miałby wszystkie tokeny dla każdego zasobu w Twojej witrynie.string = (Digest::MD5.hexdigest "#{SecureRandom.hex(10)}-#{DateTime.now.to_s}")
Może to być pomocne:
Jeśli chcesz usunąć dowolny znak specjalny niż umieszczony w pierwszym argumencie „+ / =”, a dowolny znak umieszczony w drugim argumencie „0aZ” i 15 to długość tutaj.
A jeśli chcesz usunąć dodatkowe spacje i znak nowego wiersza, dodaj następujące rzeczy:
Mam nadzieję, że to pomoże każdemu.
źródło
SecureRandom.urlsafe_base64
osiąga to samo.możesz user has_secure_token https://github.com/robertomiranda/has_secure_token
jest naprawdę prosty w użyciu
źródło
has_secure_token
pochodzi z Rails 5, ale używałem 4.x. Postępowałem zgodnie z instrukcjami w tym artykule i teraz działa dla mnie.Spróbuj w ten sposób:
Od Ruby 1.9 generowanie uuid jest wbudowane. Użyj
SecureRandom.uuid
funkcji.Generowanie przewodników w Rubim
To było dla mnie pomocne
źródło
Aby utworzyć poprawny identyfikator GUID mysql, varchar 32
źródło
SecureRandom.uuid.tr('-','').upcase
. Sprawdź ten link, aby porównać tr i gsub.źródło
Myślę, że token powinien być traktowany tak jak hasło. Jako takie powinny być zaszyfrowane w DB.
Robię coś takiego, aby wygenerować unikalny nowy token dla modelu:
źródło