Hier ist was ich benutze. Das Token muss nicht unbedingt gehört werden, um zu erraten, es ist eher eine kurze URL-Kennung als alles andere, und ich möchte es kurz halten. Ich bin einigen Beispielen gefolgt, die ich online gefunden habe, und im Falle einer Kollision ich denke der Code unten wird das Token neu erstellen, aber ich bin mir nicht sicher. Ich bin jedoch gespannt auf bessere Vorschläge, da sich dies an den Rändern etwas rau anfühlt.
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
Meine Datenbankspalte für das Token ist ein eindeutiger Index, und ich verwende auch validates_uniqueness_of :token
für das Modell. Da diese jedoch stapelweise auf der Grundlage der Benutzeraktionen in der App erstellt werden (sie bestellen eine Bestellung und kaufen im Wesentlichen die Token), Es ist nicht möglich, dass die App einen Fehler ausgibt.
Ich denke auch, um die Wahrscheinlichkeit von Kollisionen zu verringern, füge ich am Ende eine andere Zeichenkette hinzu, etwas, die auf der Zeit basiert oder so ähnlich, aber ich möchte nicht, dass der Token zu lang wird.
- Update -
Ab dem 9. Januar 2015 . ist die Lösung nun in Rails 5 ActiveRecord's implementiert sichere Token-Implementierung .
- Rails 4 & 3 -
Nur zum späteren Nachschlagen, Erstellen eines sicheren zufälligen Tokens und Sicherstellen, dass es für das Modell eindeutig ist (bei Verwendung von Ruby 1.9 und ActiveRecord):
class ModelName < ActiveRecord::Base
before_create :generate_token
protected
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless ModelName.exists?(token: random_token)
end
end
end
Bearbeiten:
@ kain schlug vor und ich stimmte zu, begin...end..while
in dieser Antwort durch loop do...break unless...end
zu ersetzen, da frühere Implementierungen in Zukunft möglicherweise entfernt werden.
Edit 2:
Bei Rails 4 und Concern würde ich empfehlen, dies in Concern zu verschieben.
# app/models/model_name.rb
class ModelName < ActiveRecord::Base
include Tokenable
end
# app/models/concerns/tokenable.rb
module Tokenable
extend ActiveSupport::Concern
included do
before_create :generate_token
end
protected
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless self.class.exists?(token: random_token)
end
end
end
Ryan Bates verwendet in seinem Railscast ein nettes bisschen Code für Beta-Einladungen . Dies erzeugt eine alphanumerische Zeichenfolge mit 40 Zeichen.
Digest::SHA1.hexdigest([Time.now, Rand].join)
In diesem Artikel werden einige recht glatte Methoden gezeigt:
Mein Favorit ist folgender:
Rand(36**8).to_s(36)
=> "uur0cj2h"
Dies kann eine späte Antwort sein, aber um die Verwendung einer Schleife zu vermeiden, können Sie die Methode auch rekursiv aufrufen. Es sieht aus und fühlt sich für mich etwas sauberer an.
class ModelName < ActiveRecord::Base
before_create :generate_token
protected
def generate_token
self.token = SecureRandom.urlsafe_base64
generate_token if ModelName.exists?(token: self.token)
end
end
Wenn Sie etwas Einzigartiges wünschen, können Sie Folgendes verwenden:
string = (Digest::MD5.hexdigest "#{ActiveSupport::SecureRandom.hex(10)}-#{DateTime.now.to_s}")
dies erzeugt jedoch eine Zeichenfolge mit 32 Zeichen.
Es gibt jedoch einen anderen Weg:
require 'base64'
def after_create
update_attributes!(:token => Base64::encode64(id.to_s))
end
zum Beispiel für eine ID wie 10000 wäre das generierte Token wie "MTAwMDA =" (und Sie können es einfach für die ID dekodieren, machen Sie einfach
Base64::decode64(string)
Das kann hilfreich sein:
SecureRandom.base64(15).tr('+/=', '0aZ')
Wenn Sie ein Sonderzeichen entfernen möchten, geben Sie im ersten Argument '+/=' ein, und in das zweite Argument '0aZ' und 15 wird die Länge eingefügt.
Und wenn Sie die zusätzlichen Leerzeichen und das neue Linienzeichen entfernen möchten, fügen Sie die folgenden Dinge hinzu:
SecureRandom.base64(15).tr('+/=', '0aZ').strip.delete("\n")
Ich hoffe, das hilft jedem.
Versuchen Sie es so:
Ab Ruby 1.9 ist die Erzeugung von Uuids integriert. Verwenden Sie die SecureRandom.uuid
-Funktion.
Erstellen von Hilfslinien in Ruby
Das war hilfreich für mich
sie können Benutzer has_secure_token https://github.com/robertomiranda/has_secure_token
ist wirklich einfach zu bedienen
class User
has_secure_token :token1, :token2
end
user = User.create
user.token1 => "44539a6a59835a4ee9d7b112b48cd76e"
user.token2 => "226dd46af6be78953bde1641622497a8"
Zum Erstellen einer ordnungsgemäßen mysql, varchar 32-GUID
SecureRandom.uuid.gsub('-','').upcase
def generate_token
self.token = Digest::SHA1.hexdigest("--#{ BCrypt::Engine.generate_salt }--")
end
Ich denke, das Token sollte wie ein Passwort behandelt werden. Daher sollten sie in der DB verschlüsselt sein.
Ich mache so etwas, um ein einzigartiges neues Token für ein Modell zu generieren:
key = ActiveSupport::KeyGenerator
.new(Devise.secret_key)
.generate_key("put some random or the name of the key")
loop do
raw = SecureRandom.urlsafe_base64(nil, false)
enc = OpenSSL::HMAC.hexdigest('SHA256', key, raw)
break [raw, enc] unless Model.exist?(token: enc)
end