您的位置:首页 > 健康 > 养生 > 电子工程院官网_公众号开发网站_sem招聘_安卓优化大师老版本

电子工程院官网_公众号开发网站_sem招聘_安卓优化大师老版本

2024/12/22 8:07:34 来源:https://blog.csdn.net/2301_81022805/article/details/144491834  浏览:    关键词:电子工程院官网_公众号开发网站_sem招聘_安卓优化大师老版本
电子工程院官网_公众号开发网站_sem招聘_安卓优化大师老版本

目录

  • 1. 初始化项目
  • 2. 配置环境变量
  • 3. 更新数据库
  • 4. 编写路由函数
  • 5. 前端调用接口

1. 初始化项目

前端根目录:/web
后端根目录:/api_server
安装依赖:

npm install express mysql nodemailer randomstring dotenv

其中,nodemailer是用来发送验证码的node.js依赖库, randomstring是用于生成随机字符串的 Node.js 库(即在这里生成验证码),dotenv用于在.env文件中配置敏感信息,避免直接暴露在代码中

2. 配置环境变量

在根目录/api_server下创建/.env文件

EMAIL_SERVICE=smtp.126.com  // 使用网易邮箱发送验证码
EMAIL_PORT=465  # 使用SSL的端口
EMAIL_SECURE=true  # 使用SSL
EMAIL_USER=YOUREMAIL@126.com  // 用你的邮箱码代替
EMAIL_PASS=YOURPASSWORD   // 客户端授权密码
DB_HOST=localhost
DB_USER=YOURUSERNAME  // 用你的数据库用户名代替
DB_PASSWORD=YOURUSERPASSWORD  // 用你的数据库密码代替
DB_NAME=YOURDBNAME  // 用你的数据库名代替

在后端入口文件中导入

require('dotenv').config()

3. 更新数据库

在你的项目数据库中添加列:email(存放邮箱号)、 code(存放验证码)、expires_at(存放验证码过期时间)

4. 编写路由函数

/api_server/router/user.js

// 登录路由
router.post('/login', userHandler.login)// 发送验证码路由
router.post('/send-verification-code', userHandler.sendVerificationCode)

/api_server/router_handler/user.js

// 创建可重用的 transporter 对象用于发送邮件
const transporter = nodemailer.createTransport({host: 'smtp.126.com', // SMTP服务器地址port: 465, // 端口号secure: true, // 使用SSLauth: {user: process.env.EMAIL_USER,pass: process.env.EMAIL_PASS}
})// 辅助函数:生成并存储验证码
const generateAndStoreVerificationCode = async (email) => {// 生成验证码const code = randomstring.generate({length: 6,  //验证码长度charset: 'numeric'  //可以选择 'alphabetic', 'numeric', 'hexadecimal', 'binary' 或者自定义字符集})// 存储验证码// const createdAt = new Date()const expiresAt = new Date(Date.now() + 5 * 60 * 1000) // 验证码有效期为 5 分钟try {const sqlStr = 'UPDATE user SET code=?, expires_at=? WHERE email=?'await db.query(sqlStr, [code, expiresAt, email])return { code, expiresAt }} catch (error) {console.error('存储验证码失败:', error)throw error}
}const util = require('util')
const query = util.promisify(db.query).bind(db)
// 辅助函数:验证验证码
const verifyCode = async (email, inputCode) => {try {// 定义查找该用户验证码的sql语句const sqlStr = 'select * from user where email=? and expires_at > NOW()'// 执行sql语句const results = await query(sqlStr, [email])if (results.length === 0) {return false}// 拿到用户数据库中存储的验证码const storeCode = results[0].code// 比较验证if (storeCode === inputCode) {// 验证成功后删除验证码const sqlStr_delete_code = 'UPDATE user SET code = null WHERE email=?'db.query(sqlStr_delete_code, [email])return true}return false} catch (error) {console.error('验证验证码失败:', error)throw error}
}// 邮箱登录时发送验证码的处理函数
exports.sendVerificationCode = async (req, res) => {// 接收邮箱号const { email } = req.bodyif (!email) {return res.send({ status: 1, message: '请提供邮箱地址' })}try {const { code, expiresAt } = await generateAndStoreVerificationCode(email)// 构建邮件内容const mailOptions = {from: process.env.EMAIL_USER,to: email,subject: `您的验证码 ${code}`,text: `您好,您的验证码是:${code}。请不要告诉他人。验证码将在 ${expiresAt.toISOString()} 前有效。`,html: `<b>你的验证码是 ${code},请勿告诉他人。</b>` // HTML 内容// 发送邮件await transporter.sendMail(mailOptions)res.send({status: 0, message: '验证码已发送,请查收邮件' })} catch (error) {res.send({status: 1, message: '发送验证码时出错' })}
}// 用户登录的处理函数
exports.login = (req, res) => {// 定义邮箱密码登陆方式的sql语句const sqlStr_email = 'select * from user where email=?'// 执行sql语句,根据邮箱查询用户信息db.query(sqlStr_email, [userInfo.email], async (err, results) => {// 判断是否查询成功if (err) {return res.send({ status: 1, message: err })}// 执行sql语句成功,但是获取的条数不等于1if (results.length === 0) {return res.send({ status: 1, message: '该用户不存在' })} else if (results.length !== 1) {return res.send({ status: 1, message: '登录失败' })}// TODO:判断验证码是否正确const isTrue = await verifyCode(userInfo.email, userInfo.code)// 验证码错误console.log('isTrue:', isTrue)      if (!isTrue) {return res.send({ status: 1, message: '验证码错误或已过期'})}})····}

【注意】:验证验证码函数使用时需要先导入util 模块,将 Node.js 中传统的基于回调的 API 转换为返回 Promise 的形式,否则无法直接通过const results = await db.query(sqlStr, [email])拿到查找的返回值

5. 前端调用接口

/web/api/user.js

// 登录接口
export const useLoginService = ({ email, code }) => {return request.post(...', { email, code })
}// 发送验证码
export const useSendVerificationCode = ({ email }) => {return request.post('...', { email })
}

/web/views/login

<script>
// 登录点击事件
const login = async () => {const res = await useLoginService(formModel.value)console.log(res + isMail.value) if (res.data.status === 1) {ElMessage.error(res.data.message)} else {userStore.setToken(res.data.token)// 登陆成功,跳转到首页router.push('/')ElMessage.success('登录成功')}
}// 定义变量存储发送验证码间隔时间
const defaultSecond = 60  // 默认60s
const second = ref(defaultSecond)  // 倒计时
// 定时器id
let timeId = 0
// 判断按钮是否禁用
// true为禁用
// false为不禁用
const isBtnDown = ref(false)
// 发送验证码事件
const sendCode = async () => {const res = await useSendVerificationCode(formModel.value)console.log(res)  if (res.data.status === 0) {console.log(111)ElMessage.success('验证码发送成功')// 开始倒计时timeId = setInterval(() => {// 禁用按钮isBtnDown.value = truesecond.value--if (second.value <= 0) {// 清除定时器clearInterval(timeId)// 归位second.value = defaultSecondisBtnDown.value = false}}, 1000)}
}// 组件卸载前执行
onUnmounted(() => {if (timeId) {clearInterval(timeId)}
})
</script>
<template><el-form-item prop="code"><el-input style="width: 140px;" v-model="formModel.code" :prefix-icon="Key" placeholder="请输入验证码"/><el-button style="width: 100px;" @click="sendCode" :disabled="isBtnDown">{{ defaultSecond === second ? '发送验证码' : `${second}秒后重新发送` }}</el-button></el-form-item><el-form-item><el-button @click="login" class="login-btn" type="primary" round>登录</el-button></el-form-item>
</template>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com