用户邮箱验证实现思路
最近在做个网站的后台,使用了JWT 实现了用户验证,并在这个基础上实现用户邮箱验证。对于 JWT 的原理,本文将不会涉及太多,如果你不是很懂 JWT,建议你弄懂了再看这篇文章。
2018.6.4 更新
经过实践,我觉得还是把 authEmail 放到 users 集比较好,独自放到 unAuthEmailUser 集,进行读取存入数据还要专门查一个表,非常不方便。
JWT 实现用户登录
在说邮箱验证之前,先简单讲下 JWT 是如何实现用户验证的。
当用户登录时,验证完用户名和密码后,将 uid(用户id)和 iat(该 JWT 创建时间) 放入到 playload 中,使用密钥生成签名,最后组成 JWT,发送给客户端。客户端把这个 token 存在 localStorage 或 cookies 中。
客户端每次发起需要权限的请求,都会携带这个 jwtToken。后台对 jwtToken 进行校验,发现没问题,则取出 jwt 的 payload 里的内容(注意 jwt 的一个优点是不需要数据库)。通过计算 iat 的时间加上后台设置的有效期是否大于当前时间来判断 token 是否过期,没过期就把 uid 保存在请求对象中。如果 token 没通过验证,则无法继续后面需要权限的操作。
添加邮箱验证功能
场景
用户注册账户(填写用户名、密码、邮箱)后,会发送一封邮件给用户的邮箱。邮件里面有个链接,用户点击后,邮箱就被验证了。用户如果没有进行验证的话,是不允许一些操作的,如发表文章(防止恶意注册用户)。
流程图
验证.png实现
下面就开始介绍实现过程。
首先,用户第一次注册的时候,在 user 表中创建了用户信息后,给客户端返回一个前面说到的 jwtToken。但这个 jwt 的 payload 要添加多一个属性 unAuthEmail,并设置为 true, 说明当前用户没有进行邮箱验证。
与此同时我们还要将生成的 用户id 存储到要给一个名为 unAuthEmailUser(没有进行邮箱验证的用户表) 的表中。
unAuthEmailUser 表主要是记录没有进行邮箱验证的用户id,当然你也可以在 user 表中加个表字段来记录,不过我考虑到不进行邮箱验证的用户不会太多,就独立出这个个表了(觉得大概能提升查表速度)。
对于邮箱验证,我们也需要一个 token(为了和前面的验证用户token进行区分,我们在这里将它称为 emailToken)。这里我也使用了 jwt 的方式,密钥可以用和前面相同的,也可以用新的。payload 部分,需要放置 uid 和 iat。生成 emailToken 后,将它作为 验证连接的 token 的值。如
https://yoursite.com/emailVerification?token=2f1f4cee1f0.c94560a75cc3b.6347f45ab
然后后台会将发送一封邮件给用户的邮箱(需要查询 user 表获得邮箱地址),里面附有这个邮箱验证链接。
用户点击这个链接,就向 /emailVerification
路由传递了一个 token 参数。如果 Emailtoken 通过了验证,且没有过期(这次设置的过期时间要短点),将 unAuthEmailUser 含有对应 uid 的数据删除。这时候生成一个新的不含 unAuthEmail 的用户验证用的 Token 发送给客户端(表明当前用户已经进行过邮箱验证了)
用户每次登陆生成 token 的时候,都要查询 unAuthMailUser 表,如果有该用户,返回的 token 中需要有 unAuthMail=true,否则不带该属性。
另外,用户还可以通过点击 “发送邮箱验证邮件” 按钮,生成 emailToken 发到你的邮箱。
总结
用户验证 token 和邮箱 token 都使用了 JWT。我们创建了一个表来保存未进行邮箱验证的,用户每次生成用户身份验证用的 token 都要查询这个表。如果表中包含当前用户id,说明未进行邮箱验证,token 需要添加 unAuthMail: true;否则不添加这个属性。点击验证链接进行验证时,如果 token 有效,移除 unAutnMailUser 表中的对应用户id,并生成一个新的不含 unAuthMail 的 token 替换掉原来客户端保存的旧 token
网友评论