web-dev-qa-db-fra.com

Comment générer une chaîne de sécurité d'url aléatoire avec Elixir

Je dois être en mesure de générer des chaînes aléatoires sécurisées pour les URL afin de pouvoir les utiliser dans les liens (comme dans un lien d'activation envoyé à la messagerie d'un utilisateur), alors comment puis-je le générer? Existe-t-il un moyen de le faire uniquement avec Elixir ou je devrais utiliser une bibliothèque?

35
NoDisplayName

Ce que vous pouvez faire à la place est de générer une chaîne codée en Base64 à utiliser comme jeton de confirmation. Ce jeton de confirmation sera ensuite enregistré dans votre base de données et transmis en tant que paramètres au lien d'activation. Votre URL d'activation ressemblerait à quelque chose comme:

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

L'assistant d'URL ci-dessus suppose que vous disposez d'un MyApp.ActivationController et un confirm/2 action dans ce contrôleur. Pour générer le confirm_id, vous pourriez faire:

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

# random_string(64)

Dans ton MyApp.ActivationController.confirm/2, vous pourriez avoir le code 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

J'espère que cela pourra aider!

50
Gjaldon

Vous pouvez facilement définir un module pour ce faire. Dans cet exemple, @chars détermine quels caractères apparaissent dans vos chaînes générées.

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"
10
Nathan Long

Comme indiqué dans le commentaire de @ JimGray, votre spécification doit vraiment être en termes de quantité d'entropie que vous souhaitez représenter par les chaînes de sécurité d'URL aléatoires. Quelque chose du genre "J'ai besoin de N bits" parce que quelqu'un vous a dit d'utiliser N bits, ou "Je veux éviter de répéter dans N chaînes et je peux accepter un risque de 1 sur n de collision". Dans les deux cas, il s'agit directement d'entropie et seulement indirectement de longueur de chaîne.

Par exemple, assurez-vous que si vous utilisez une solution comme la réponse @Gjaldon, vous comprenez même si 512 bits de caractère aléatoire sont utilisés, la quantité d'entropie pour la chaîne réelle générée par random_string(64) est de 320 bits. Que cela soit suffisant dépend bien sûr de votre scénario, qui, comme indiqué ci-dessus, est probablement mieux exprimé par exemple: "J'ai besoin d'un million de chaînes avec pas plus d'un 1 dans un billion de risques de répétition", auquel cas 320 bits sont surpuissance brute car vous n'en auriez besoin que de 79.

Si vous voulez plus de contrôle et de compréhension sur la génération de chaînes aléatoires, regardez EntropyString . Avec cette bibliothèque, vous pouvez faire quelque chose comme ceci pour obtenir une chaîne avec 256 bits d'entropie:

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

Ou si vous réalisez qu'un million de chaînes avec un risque de répétition de 1 sur un billion est suffisant, vous pouvez configurer votre génération d'ID comme:

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"

Quoi qu'il en soit, le contrôle et la compréhension sont de bonnes choses à avoir.

4
dingo sky