Soru Elixir ile rastgele bir url güvenli dizesi nasıl oluşturulur


Ben rastgele url güvenli dizeleri üretmek mümkün olması gerekir bu yüzden ben bağlantılarda kullanabilirsiniz (bir kullanıcının e-postaya gönderilen bir aktivasyon linki gibi), bu yüzden nasıl oluşturabilirim? Bunu sadece Elixir ile yapmanın bir yolu var mı yoksa kütüphaneyi kullanmak zorunda mıyım?


32
2017-08-14 02:59


Menşei




Cevaplar:


Bunun yerine, bir onay belirteci olarak kullanılacak Base64 kodlu bir dize oluşturmaktır. Bu onay belirteci daha sonra DB'nize kaydedilir ve aktivasyon bağlantısına params olarak geçirilir. Aktivasyon URL’niz şöyle bir şeye benzeyecektir:

activation_url(MyApp.Endpoint, :confirm, confirm_id: confirm_id)

Yukarıdaki URL yardımcısı, bir MyApp.ActivationController ve bir confirm/2 o denetleyicideki eylem. Üretmek için confirm_idYapabilirsin:

def random_string(length) do
  :crypto.strong_rand_bytes(length) |> Base.url_encode64 |> binary_part(0, length)
end

# random_string(64)

Senin içinde MyApp.ActivationController.confirm/2kod benzeri olabilir:

def confirm(conn, %{"confirm_id" => confirm_id}) do
  user = Repo.get_by(User, confirm_id: confirm_id)
  User.confirm(user)
  conn
  |> put_flash(:info, "Account confirmed!")
  |> redirect(to: "/")
end

Umarım yardımcı olur!


41
2017-08-14 04:58



Sonucu olacak random_string/1 güvenli ol - NoDisplayName
Url güvenli Base64 sürümünü kullanmak için cevabı güncelledim. - Gjaldon
Cevabınız için çok teşekkür ederim - NoDisplayName
Rica ederim! - Gjaldon
Yan not: Sık sık, dizgi uzunluğu yerine bir hedef rastgele bit sayısı istersiniz, ör. oturum belirteçleri en az 256 bit (32 bayt) olmalıdır. Bunu başarmak için, binary_part () çağrısı atlanmalıdır; bu noktada nokta uzunluğu, oluşturulan anahtarın bayt cinsinden entropisi olacaktır. - Jim Gray


Bunu yapmak için kolayca bir modül tanımlayabilirsiniz. Bu örnekte, @chars Oluşturduğunuz dizelerinizde hangi karakterlerin görüneceğini belirler.

defmodule StringGenerator do
  @chars "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |> String.split("")

  def string_of_length(length) do
    Enum.reduce((1..length), [], fn (_i, acc) ->
      [Enum.random(@chars) | acc]
    end) |> Enum.join("")
  end
end

StringGenerator.string_of_length(3) # => "YCZ"

9
2017-07-11 20:06



Bunu not et @chars Ayrıca, oluşturulan dizenin daha kısa olabileceği anlamına gelen boş dizeyi de içerir. length. Sadece bir karakter kullanımının dizelerini almak için String.split("", trim: true). - Sven Koschnicke
Bunun için teşekkürler. Alternatif olarak kullanabileceğinizi düşünün String.codepoints yerine String.split. Ayrıca biraz temizleyici kullanarak olabilir mapfwiw: 1..length |> Enum.map(fn _i -> Enum.random(@chars) end) |> Enum.join(""). - Joe Freeman


@ JimGray'ın yorumunda belirtildiği gibi, spesifikasyonunuz gerçekten rastgele URL güvenli dizeleriyle temsil etmek istediğiniz entropi miktarı açısından olmalıdır. "N bitlerine ihtiyacım var" satırlarında bir şey var çünkü birisi N bitlerini kullanmanı söyledi, ya da "N dizelerinde tekrardan kaçınmak istiyorum ve bir çarpışmada 1 riskini kabul edebilirim". Her iki durumda da, doğrudan entropi hakkında ve sadece dize uzunluğu ile dolaylı olarak ilgilidir.

Örneğin, @Gjaldon 'gibi bir çözüm kullanırsanız, 512 bit rastgeleliğin kullanıldığını anladığınızdan emin olun, gerçek dizge tarafından oluşturulan entropi miktarı random_string(64) 320 bittir. Bunun yeterli olup olmadığı elbette ki, yukarıda da belirtildiği gibi, muhtemelen en iyi şekilde ifade edildiği gibi, "trilyon tekrarlama riskinde 1'den fazla olmayan bir milyon dizeye ihtiyacım var", ki bu durumda 320 bit olur. Sadece 79'a ihtiyacın olduğu gibi.

Daha fazla kontrol ve rastgele dizeler oluşturma anlayışını istiyorsanız, bakınız EntropyString. Bu kitaplıkla, 256 bit entropi ile bir dize almak için aşağıdaki gibi bir şey yapabilirsiniz:

iex> defmodule Id, do: use EntropyString, charset: charset64
iex> Id.token
"ziKYK7t5LzVYn5XiJ_jYh30KxCCsLorRXqLwwEnZYHJ"

Ya da bir milyonda 1 trilyon tekrar riski olan bir milyon dizge olduğunu fark ederseniz Yeterli, kimlik oluşturmayı şöyle yapabilirsin:

iex> defmodule Id do
...>   use EntropyString, charset: charset64
...>   @bits entropy_bits(1.0e6, 1.0e12)
...>   def random, do: Id.random_string(@bits)
...> end
iex> Id.random
"FhlGVXOaXV9f3f"

Her iki şekilde de, kontrol ve anlayış sahip olmak için güzel şeylerdir.


2
2017-09-01 16:42