我需要能够生成随机url安全字符串,以便我可以在链接中使用它们(比如发送到用户电子邮件的激活链接),那么我该如何生成呢?有没有办法只使用Elixir或者我必须使用一些库?
答案 0 :(得分:48)
您可以做的是生成一个Base64编码的字符串,用作确认令牌。然后,此确认令牌将保存到您的数据库,并作为参数传递给激活链接。您的激活网址如下所示:
activation_url(MyApp.Endpoint, :confirm, confirm_id: confirm_id)
上面的网址助手假定您在该控制器中有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
中,你可以拥有代码:
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
希望有所帮助!
答案 1 :(得分:10)
You can easily define a module to do this. In this example, @chars
determines what characters appear in your generated strings.
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"
答案 2 :(得分:3)
正如@ JimGray评论中所述,您的规范应该是您想要通过随机URL安全字符串表示的熵数量。类似于"我需要N位"因为有人告诉你要使用N位,或者#34;我想避免在N个字符串中重复,我可以接受n中碰撞的风险1"。无论哪种方式,它都直接关于熵,并且只是间接地关于字符串长度。
例如,如果您使用@ Gjaldon'等解决方案,请务必使用即使使用了512位随机性,你也能理解,random_string(64)
生成的实际字符串的熵数是320位。这是否足够当然取决于您的情况,如上所述,可能最好表达为,例如,"我需要一百万个字符串,一万亿次重复风险不超过1# 34;,在这种情况下,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"
无论哪种方式,控制和理解都是很好的事情。