如何使用Timex为验证链接设置超时(不使用Coherence等认证包)
使用Timex实现验证链接的超时机制
没问题,咱们完全可以用Timex手动搞定这个需求,不用依赖任何认证类包,步骤其实很清晰:
1. 数据库表新增过期时间字段
首先你需要在存储验证链接的表(比如verification_tokens)里加一个expires_at字段,用来记录链接的失效时间。如果用Ecto的话,Schema可以这么定义:
defmodule YourApp.VerificationToken do use Ecto.Schema import Ecto.Changeset alias Timex.DateTime schema "verification_tokens" do field :token, :string field :user_id, :integer # 关联到对应用户 field :expires_at, :utc_datetime # 存储UTC时间,避免时区问题 timestamps() end def changeset(token, attrs) do token |> cast(attrs, [:token, :user_id, :expires_at]) |> validate_required([:token, :user_id, :expires_at]) end end
2. 生成验证链接时计算过期时间
当你生成验证token并存入数据库时,用Timex计算出过期时间。比如设置链接24小时后失效:
# 生成安全的随机token token = :crypto.strong_rand_bytes(16) |> Base.url_encode64(padding: false) # 计算24小时后的UTC时间作为过期时间 expires_at = Timex.now() |> Timex.add(Timex.Duration.from_hours(24)) # 存入数据库 YourApp.Repo.insert!(YourApp.VerificationToken.changeset(%YourApp.VerificationToken{}, %{ token: token, user_id: user.id, expires_at: expires_at })) # 把包含token的链接通过邮件发给用户,比如"https://your-app.com/verify?token=#{token}"
这里推荐用UTC时间存储,避免不同时区导致的过期时间计算偏差,Timex的Timex.now()默认返回的就是UTC时间(只要你的项目时区配置正确)。
3. 验证链接时检查是否过期
当用户点击链接访问验证接口时,先根据token从数据库取出对应记录,再用Timex对比当前时间和过期时间:
def verify_token(token) do case YourApp.Repo.get_by(YourApp.VerificationToken, token: token) do nil -> {:error, :invalid_token} token_record -> # Timex.compare返回1表示当前时间晚于过期时间,即链接已失效 case Timex.compare(Timex.now(), token_record.expires_at) do 1 -> # 顺便删除过期token,避免数据库冗余 YourApp.Repo.delete(token_record) {:error, :token_expired} _ -> # 验证通过,执行后续逻辑(比如激活用户) {:ok, token_record.user_id} end end end
Timex.compare/2的返回值规则:
-1:第一个时间早于第二个0:两个时间完全相等1:第一个时间晚于第二个
所以返回1时,就说明链接已经过期失效了。
额外优化:定期清理过期token
为了避免数据库堆积大量过期的无效token,你可以加个定时任务自动清理,比如用Oban或者简单的Task:
def clean_expired_tokens do expired_at = Timex.now() YourApp.Repo.delete_all( from t in YourApp.VerificationToken, where: t.expires_at < ^expired_at ) end
内容的提问来源于stack exchange,提问作者Sh4dy
相关产品推荐
相关产品推荐

