springboot+vue 实现邮箱验证码

大家好,今天给大家带来一个开箱即用的功能:邮箱验证码。 为你的项目增加特色,自然而然就会过答辩!

源码适用于springboot项目,前端是vue。 直接将源码拷贝到你的项目就可以了,无需任何修改!!

实现效果

视频演示

实现步骤

1. 开通QQ邮箱服务器

首先我们需要有一个QQ, 只要能进QQ邮箱即可,用账号密码登录QQ邮箱, 进入邮箱后点击顶部设置

然后切换到账号

拉到下面的POP3/IMAP.... 这一项,开启我们的服务(这里截图是我已经开了)。

然后会获取一段授权码,发邮件代码会用到。

到此你的个人qq邮箱就可以当服务器发邮件了。

2. 后端实现

首先我们需要引入maven, 在项目的目录下的pom.xml 的 <dependencies>节点 添加下面内容:


1234 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>

  

环境配置


spring:
  mail:
    host: smtp.qq.com
    username: 你的邮箱(3571289092@qq.com)
    password: 你的授权码(上面生成的)
    properties.mail.smtp:
      auth: true
      starttls:
        enable: true
        required: true
        

获取邮箱验证码接口和注册接口代码:


@RestController
@RequestMapping("/reg")
public class RegisterController {

    @Autowired
    Emails emails;

    @PostMapping("get-code")
    public V getCode(@RequestBody User user) {
        if (StringUtils.isEmpty(user.getEmail())) {
            return V.err("邮箱为空");
        }
        if (!emails.isValidEmail(user.getEmail())) {
            return V.err("邮箱格式错误");
        }
        //  这里可以从数据库中根据邮箱查询用户,如果数据存在, 提示 该邮箱已经被注册

        // 发送邮箱验证码
        String code = emails.send(user);
        // 验证码 存入缓存
        emails.putCache(user.getEmail(), code);
        System.out.println("用户获取邮箱验证码 : " + user.getEmail() + " , code:" + code);
        return V.ok();
    }

    @PostMapping("register")
    public V register(@RequestBody User user) {
        if (StringUtils.isEmpty(user.getEmail()) || !emails.isValidEmail(user.getEmail())
        || StringUtils.isEmpty(user.getCode())) {
            return V.err("参数错误");
        }

        // 从缓存中判断验证码
        if (!emails.getCache(user.getEmail()).equals(user.getCode().trim())) {
            return V.err("邮箱验证码错误");
        }
        System.out.println("验证码验证成功,开始注册");
        // 下面为验证码正确

        // 进行你的注册逻辑

        return V.ok() ;
    }

}

Emails 类是我封装的一个邮箱工具类, 支持 发送邮箱,邮箱验证码校验,邮箱校验 等功能。

项目的前后端整体源码我已经整理清楚,移步获取:

gitcode典康姆/hadluo2/func_code.git

3. 后端实现

注册页面代码:


<template>
  <div class="register-container">
    <h2>用户注册</h2>
    <div class="register-form">
      <div class="form-item">
        <label>邮箱:</label>
        <input type="email" v-model="email" placeholder="请输入邮箱">
      </div>
      <div class="form-item verification-code">
        <label>验证码:</label>
        <input type="text" v-model="verificationCode" placeholder="请输入验证码">
        <button @click="sendVerificationCode" :disabled="cooldown > 0">
          {{ cooldown > 0 ? `${cooldown}秒后重试` : '获取验证码' }}
        </button>
      </div>
      <div class="form-item">
        <label>密码:</label>
        <input type="password" v-model="password" placeholder="请输入密码">
      </div>
      <button class="register-btn" @click="handleRegister">注册</button>
    </div>
  </div>
</template>

<script>
import { getCode, register } from '@/api/registerApi'
import { ElMessage } from 'element-plus'

export default {
  name: 'Register',
  data() {
    return {
      email: '3571289092@qq.com',
      verificationCode: '',
      password: '',
      cooldown: 0
    }
  },
  methods: {
    async sendVerificationCode() {
      if (!this.email) {
        ElMessage.warning('请输入邮箱地址');
        return;
      }
      try {
        await getCode(this.email);
        this.startCooldown();
        ElMessage.success('验证码已发送,请查收邮件');
      } catch (error) {
        ElMessage.error('发送验证码失败');
      }
    },
    startCooldown() {
      this.cooldown = 60;
      const timer = setInterval(() => {
        this.cooldown--;
        if (this.cooldown <= 0) {
          clearInterval(timer);
        }
      }, 1000);
    },
    async handleRegister() {
      if (!this.email || !this.verificationCode || !this.password) {
        ElMessage.warning('请填写完整信息');
        return;
      }
      try {
        await register({
          email: this.email,
          code: this.verificationCode,
          password: this.password
        });
        ElMessage.success('注册成功');
        this.$router.push('/login');
      } catch (error) {
       console.log(error);
     
      }
    }
  }
}
</script>

<style scoped>
.register-container {
  max-width: 500px;
  margin: 50px auto;
  padding: 20px;
}

.register-form {
  background: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.form-item {
  margin-bottom: 20px;
}

.form-item label {
  display: block;
  margin-bottom: 8px;
}

.form-item input {
  width: 100%;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  box-sizing: border-box;
}

.verification-code {
  display: flex;
  gap: 10px;
}

.verification-code input {
  flex: 1;
}

.verification-code button {
  padding: 8px 15px;
  background: #409EFF;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.verification-code button:disabled {
  background: #a0cfff;
  cursor: not-allowed;
}

.register-btn {
  width: 100%;
  padding: 12px;
  background: #409EFF;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
}

.register-btn:hover {
  background: #66b1ff;
}
</style>

registerApi.js代码:


import request from '@/utils/requests'

// 获取验证码
export function getCode(email) {
  return request({
    url: '/reg/get-code',
    method: 'post',
    data: {
      email
    }
  })
}

// 添加广告
export function register(data) {
  return request({
    url: '/reg/register',
    method: 'post',
    data
  })
}

requets.js代码:


import axios from 'axios'
import { ElMessage } from 'element-plus'

const service = axios.create({
  baseURL: '/api',
  timeout: 5000
})

// 请求拦截器
service.interceptors.request.use(
  config => {
    // 在请求发送之前做一些处理,比如添加token
    const token = localStorage.getItem('token')
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  error => {
    console.log(error)
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  response => {
    const res = response.data
    // 这里可以根据后端的响应结构进行调整
    if (res.code === 0) {
      return res.data
    } else {
      ElMessage.error(res.msg || '请求失败')
      return Promise.reject(new Error(res.msg || '请求失败'))
    }
  },
  error => {
    console.log('err' + error)
    ElMessage.error(error.message || '请求失败')
    return Promise.reject(error)
  }
)

// 封装GET请求
export function get(url, params) {
  return service({
    url,
    method: 'get',
    params
  })
}

// 封装POST请求
export function post(url, data) {
  return service({
    url,
    method: 'post',
    data
  })
}

// 封装PUT请求
export function put(url, data) {
  return service({
    url,
    method: 'put',
    data
  })
}

// 封装DELETE请求
export function del(url, params) {
  return service({
    url,
    method: 'delete',
    params
  })
}

export default service

到此,前后端实现完毕!!!


用户评论

Java源码|游戏源码|JavaScript+html前端源码|PHP源码|单机游戏

本站资源收集与互联网开源,经站长分类整理,若无意中侵犯了您的知识产权,
请联系邮箱: 3571289092@qq.com告知,本站将立即删除并致以最深的歉意!

关于我们
联系我们

湘公网安备 43010402000935号 | 湘ICP备2021002996号-1

开通VIP免费下载资源
客服QQ 3571289092