Подтвердить что ты не робот

Как создать случайную безопасную строку с Elixir

Мне нужно иметь возможность генерировать случайные строки с правильными URL-адресами, чтобы я мог использовать их в ссылках (например, в ссылке активации, отправленной пользователю электронной почты), поэтому как я могу ее создать? Есть ли способ сделать это только с Elixir или мне нужно будет использовать некоторую библиотеку?

4b9b3361

Ответ 1

Вместо этого вы можете создать строку с кодировкой Base64, которая будет использоваться в качестве токена подтверждения. Этот токен подтверждения будет затем сохранен в вашей БД и передан в качестве параметров для ссылки активации. Ваш URL-адрес активации будет выглядеть примерно так:

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

Вышеупомянутый помощник URL предполагает, что в этом контроллере есть действие MyApp.ActivationController и confirm/2. Чтобы сгенерировать confirm_id, вы можете сделать:

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

# random_string(64)

В вашем MyApp.ActivationController.confirm/2 у вас может быть код lik:

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

Надеюсь, что это поможет!

Ответ 2

Вы можете легко определить модуль для этого. В этом примере @chars определяет, какие символы появляются в ваших сгенерированных строках.

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"

Ответ 3

Как отмечено в комментарии @JimGray, ваша спецификация должна действительно быть в терминах количества энтропии, которую вы хотите представлять случайными URL-адресами. Что-то вроде строк "Мне нужны N бит", потому что кто-то сказал вам использовать N бит, или "Я хочу избежать повторения в N строках, и я могу принять риск 1 в n столкновения". В любом случае, это непосредственно об энтропии и только косвенно о длине строки.

Например, убедитесь, что если вы используете такое решение, как ответ @Gjaldon, вы понимаете, хотя используется 512 бит случайности, количество энтропии для фактической строки, генерируемой random_string(64), составляет 320 бит. Насколько это достаточно, конечно, зависит от вашего сценария, который, как отмечено выше, вероятно, лучше всего выражается, например, "Мне нужно миллион строк с не более чем 1 триллионом риска повторения", и в этом случае 320 бит грубого избытка, поскольку вам понадобится только 79.

Если вам требуется больше контроля и понимания генерации случайных строк, посмотрите EntropyString. С помощью этой библиотеки вы можете сделать что-то вроде следующего, чтобы получить строку с 256 битами энтропии:

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

Или, если вы реализуете миллион строк с повторным риском в 1 триллион, достаточно, вы можете настроить свое генерирование Id, например:

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"

В любом случае, управление и понимание - это приятные вещи.