邮件退订的设计与实现
  • 累计撰写 120 篇文章
  • 累计收到 1 条评论

邮件退订的设计与实现

2024-10-19 / 0 评论 / 140 阅读

何为邮件退订

在平常的验证码, 推广邮件中, 我们通常会在最下角找到 退订链接。通常访问它, 我们就不会再收到他们发送的邮件。

但是, 如何以最简单, 最节省性能的方式去实现这一功能呢?

一开始

其实最简单的方式, 貌似就是在 发送邮件时, 生成一段随机字符, 存储在数据库或缓存中(已经缓存, 可直接读取), 然后拼接成一个网址, 附在邮件底部. 用户打开后 将字符串传递给后端, 从数据库或缓存中找到这段字符串所对应的邮箱.

获取到请求对定的[人]邮箱后, 将其存储至数据库[在], 后续发信时, 只需查找一次便可[旅].

这个过程其实很简单, 有没有办法让其更加简单, 发信时不去依赖服务端的持久化存储呢?

了解jwt

其实我们可以借鉴一下 jwt (json web token) 的验证思路. jwt 是由 header, payload, signature 通过小数点间隔 组成的一段字符串.

header

其中 header是由 typ和alg 组成的json 经过base64得出

 
 
 
{
"typ": "JWT",
"alg": "HS256"
}

typ是固定的, 指出这段字符为 jwt. 而 alg 则指出了签名的生成方式. 这里使用的是 sha256

payload

payload是有效负荷, 其中存储了jwt的签发单位, 签发时间, 有效时间, 公开信息 等, 它同样也是由这些信息的json 再经过base64得出.

通常情况下, payload建议包含以下字符, 但也不是必须的:

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

如, 在此处场景下, 我们可以这样

 
 
 
{
"iss": "website",
"aud": "email@example.com",
"iat": "timestamp"
}

signature

签名用于对这串 jwt 进行合法性校验. 来判断它是否经过伪造. 进行签名我们需要一个密钥, 这个密钥只能存储在服务端, 并严格保密. 这串密钥也是通常所称的 salt.

签名方式便是header中给出的alg, 如此处 我们通过 SHA256(header + payload + salt) 生成签名.

最终jwt的格式应为 header.payload.sha256(header+payload+salt)

使用

我们只需在发送邮件时, 生成这段jwt. 发送给用户, 所有的信息仅存储在用户的邮件中, 也不用担心伪造. 我们需要做的只是保证密钥的安全.

此时当用户需要退订时, 服务器接收到这段jwt后, 需先对其进行验签, 判断其是否经过伪造. 如果通过, 接着从payload中取出用户邮箱. 将其加入不发送的名单内即可.

收藏

扫描二维码,在手机上阅读

评论一下?

OωO
取消