Skip to content

Commit

Permalink
📝 实现邮箱辅助登录功能
Browse files Browse the repository at this point in the history
  • Loading branch information
Jimmylxue committed Dec 12, 2023
1 parent 11fa69f commit 7bdf9f8
Showing 1 changed file with 111 additions and 0 deletions.
111 changes: 111 additions & 0 deletions docs/front-end/折腾/实现邮箱辅助登录功能.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# 实现一个邮箱辅助登录功能

## 痛点

如果有自己折腾一些自己的网站,或者做毕设的同学,相信你们一定都遇到过这么一个问题:注册时,想用微信号、手机号、邮箱来辅助登录,但是不知道怎么接入到我们的系统中,亦或是要收费。

> - 接入微信开放平台网页登录收费。
> - 手机号短信服务收费。
> - **邮件服务,我们即可自己实现。**
我前后做了好几个小工具或者网站,这个问题技术问题一直没有被突破,近期终于实现了邮箱验证码系统。并接入了 [DODD](https://tdl.jimmyxuexue.top/#/center) 中。

## 效果

效果如下:

![image-20231212110242628](https://image.jimmyxuexue.top/img/202312121102770.png)

对应的邮箱会收到这么一条信息:

![image-20231212110424010](https://image.jimmyxuexue.top/img/202312121104097.png)

![image-20231212110500300](https://image.jimmyxuexue.top/img/202312121105345.png)

将此验证码输入之后,便可登录系统,获取对应的用户信息。

## 实现思路

下面我们来说说实现思路,整体上我们是需要解决这么两个问题:

- 通过代码的方式发送邮件。
- 将验证码&发送用户与系统进行关联,进行一些校验的逻辑。

### 发送邮件

之前 B 站上传过一个视频,讲了如何发送邮件,附上传送门 🚪:[nodejs 实现邮件服务](https://www.bilibili.com/video/BV1Dz4y1G7wm/?vd_source=b869b9e47469b5438851429bda1fb3fc)

<iframe src="//player.bilibili.com/player.html?aid=576691965&bvid=BV1Dz4y1G7wm&cid=1285265826&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

核心就是通过 [nodemailer](https://www.npmjs.com/package/nodemailer) 这个库,去帮助我们发送一些邮件。

> 这个库的核心也是去调用一些邮箱的公共接口,所以我们是需要获取自己账号的 token,并且开放一些高级权限的。
具体的如何操作不在这篇内容做详细记录,大家自行过一遍视频即可。

### 与现有系统进行关联

> 作为一名前端程序员 👨🏻‍💻,所以这一块的实现可能会有并不是非常合理的地方,还望大家可以提出更好的方案。
这里我们需要借助`redis`,之所以使用`redis`而不用`mysql`是因为它拥有更快的速度。

所以我们需要维护这么一个数据结构。key 为:`snow-server-mail-verification-code-邮箱地址`,值为随机六位数验证码。同事设置过期时间为 10 分钟。

> 设置了 10 分钟后,redis 会自动为我们清空掉这个 key
```ts
@Post('send_verification_code')
async send(@Body() body: SendMailDto) {
const { mail } = body;
if (!isQQMail(mail)) {
return { code: 500, result: '邮箱格式不正确 - 不是qq邮箱' };
}
const redis = await RedisInstance.initRedis();
const code = generateRandomCode();
const key = `snow-server-mail-verification-code-${mail}`;
redis.set(key, code);
redis.expire(key, 600); // 单位是秒
await this.nodemailerService.sendVerificationCode({ to: mail, code });
return { code: 200, result: '发送成功' };
}
```

设置上了这么个 key 之后,我们就可以在登录的时候拿上这个验证码和 key 校验一下`redis`中这个 key 是否一致,如果一致,则校验通过,给于登录的 token 之类的权限。

部分代码如下:

```ts
@Post('login_by_mail')
async loginByMail(@Body() body: LoginByMailDto) {
const { code, mail } = body;
if (!isQQMail(mail)) {
return { code: 500, result: '邮箱格式验证异常,请校验' };
}
let user = await this.usersService.findUserByMail(mail);
if (!user) {
return {
code: 10000,
result: '该邮箱未创建用户,请检查地址,或为该邮箱注册一个用户',
};
}
const redis = await RedisInstance.initRedis();
const key = `snow-server-mail-verification-code-${mail}`;
const redisCode = await redis.get(key);
if (redisCode !== code.toUpperCase()) {
return {
code: 500,
result: '验证码校验失败,请重新发送验证码进行校验',
};
}
if (redisCode) {
await redis.del(key);
}
return await this.usersService.createToken(user);
}
```

## 总结

基于以上的两个关键步骤,我们就能够在自己的系统中接入邮箱辅助登录的服务了。对于想要自己动手做一个自己网站之类的东西还是挺不错的。

感谢观看。有不清晰的地方欢迎私信。

0 comments on commit 7bdf9f8

Please sign in to comment.