基于SpringBoot的邮箱验证码功能

需要的依赖

        <!-- 发送邮件所需要的jar包-->
        <!--javaMail-->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>javax.mail-api</artifactId>
            <version>1.5.6</version>
        </dependency>
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.5.3</version>
        </dependency>

mapper层

package cn.tedu.kawasaki.mapper;


import cn.tedu.kawasaki.pojo.entity.User;
import cn.tedu.kawasaki.pojo.vo.UserVO;
import org.springframework.stereotype.Repository;
/**
 * 处理用户数据的Mapper接口
 *
 * @author Edgar
 * @version 0.0.1
 */
@Repository
public interface UserMapper {
    /**
     * 根据用户名查询用户信息
     *
     * @param email 邮箱
     * @return
     */
    UserVO selectByEmail(String email);

    /**
     * 添加用户
     *
     * @param user
     * @return
     */
    int insert(User user);

    /**
     * 更新
     *
     * @param user 用户
     * @return int
     */
    int update(User user);
}

 service层

1、service接口

package cn.tedu.kawasaki.service;
import org.springframework.transaction.annotation.Transactional;

//声明式事务
@Transactional
public interface UserService {

    /**
     * 通过电子邮件注册
     *
     * @param email    电子邮件
     * @param pwd      密码
     */
    void registerByEmail(String email, String pwd);

    /**
     * 确认电子邮件
     *
     * @param email 电子邮件
     * @param code  验证码
     */
    void confirmEmail(String email, String code);
}

2、service实现类

package cn.tedu.kawasaki.service.impl;

import cn.tedu.kawasaki.ex.ServiceException;
import cn.tedu.kawasaki.mapper.UserMapper;
import cn.tedu.kawasaki.pojo.entity.User;
import cn.tedu.kawasaki.pojo.vo.UserVO;
import cn.tedu.kawasaki.service.UserService;
import cn.tedu.kawasaki.utils.EmailUtil;
import cn.tedu.kawasaki.utils.FormatUtil;
import cn.tedu.kawasaki.web.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Random;

/**
 * 处理用户业务的实现类
 *
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Autowired
    HttpServletRequest request;

    /**
     * 通过用户的E-mail注册用户
     *
     * @param email
     * @param pwd
     * @return
     */
    @Override
    public void registerByEmail(String email, String pwd) {
        // 校验邮箱是否合法
        if (!FormatUtil.isEmail(email)) {
            // 不合法则直接抛出异常
            String message = "注册用户失败,请稍后再试";
            throw new ServiceException(ServiceCode.ERR_BAD_REQUEST,message);
        }
        //验证邮箱是否注册过
        UserVO userVO = userMapper.selectByEmail(email);
        if (userVO==null){
            //先将一个未激活的用户插入到数据库中
            User user = User.builder()
                    .email(email)
                    .password(pwd)
                    .state(0)
                    .build();
            int rows = userMapper.insert(user);
            if (rows!=1){
                String message = "注册用户失败,请稍后再试";
                throw new ServiceException(ServiceCode.ERR_INSERT,message);
            }
            //邮箱合法则发送校验邮件以便于激活用户
            judgeMail(email);
        }
        judgeMail(email);
    }
    @Override
    public void confirmEmail(String email, String code) {
        HttpSession session = request.getSession();
        String codeInSession = (String) session.getAttribute("code");
        if (code.equals(codeInSession)) {
            UserVO userVO = userMapper.selectByEmail(email);
            if (userVO==null){
                String message = "注册用户失败,请稍后再试";
                throw new ServiceException(ServiceCode.ERR_SELECT,message);
            }
            if (userVO.getState()==1){
                String message = "注册用户失败,该用户已经注册";
                throw new ServiceException(ServiceCode.ERR_SELECT,message);
            }
            // 激活这个用户
            userVO.setState(1);
            User user = User.builder()
                    .id(userVO.getId())
                    .state(userVO.getState())
                    .build();
            int rows = userMapper.update(user);
            if (rows!=1){
                String message = "注册用户失败,请稍后再试";
                throw new ServiceException(ServiceCode.ERR_UPDATE,message);
            }
            return;
        }
        String message = "注册用户失败,验证码错误";
        throw new ServiceException(ServiceCode.ERR_BAD_REQUEST,message);
    }

    /**
     * 发送给他一个校验码。
     *
     * @param email
     */
    private void judgeMail(String email) {
        HttpSession session = request.getSession();
        //生成随机验证码
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            code.append(random.nextInt(10));
        }
        String massage = "您的邮箱是"+ email+",您的验证码是:" +code.toString()+"如果不知道,请无视。" ;
        log.debug("校验码:{}",code);
        //下面有EmailUtil代码
        EmailUtil.sendMail(email, massage);
        session.setAttribute("code", code.toString());
    }


}

 controller层

package cn.tedu.kawasaki.controller;

import cn.tedu.kawasaki.service.UserService;
import cn.tedu.kawasaki.web.JsonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * 处理用户相关请求控制器
 *
 * @author Edgar
 * @version 1.0.0
 */
@Slf4j
@Api(tags = "01. 用户管理模块")
@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    UserService userService;

    /**
     * 邮件注册
     *
     * @return
     */
    @ApiOperation("邮箱注册")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "email", name = "email", example = "edgar1223@163.com"),
            @ApiImplicitParam(value = "pwd", name = "pwd", example = "123456")
    }
    )
    @PostMapping("/registerByEmail")
    public JsonResult registerByEmail(@RequestParam(value = "email", required = true) String email,
                               @RequestParam(value = "pwd", required = true) String pwd
    ) {
        userService.registerByEmail(email, pwd);
        return JsonResult.ok();
    }

    /**
     * 校验邮箱
     */
    @ApiOperation("校验邮箱")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "email", name = "email", example = "edgar1223@163.com"),
            @ApiImplicitParam(value = "code", name = "code", example = "123456")
    }
    )
    @GetMapping(value = "/confirmEmail")
    public JsonResult confirmEmail(@RequestParam(value = "email", required = true) String email,
                            @RequestParam(value = "code", required = true) String code) {
        userService.confirmEmail(email, code);
        return JsonResult.ok();
    }
}

 EmailUtil类

package cn.tedu.kawasaki.utils;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;

/**
 * 电子邮件工具类
 *
 * @author Edgar
 * @version 1.0.0
 * @date 2022/12/23
 */
public class EmailUtil {
    /**
     * 发送邮箱:XXX@163.com
     */
    private static final String MY_EMAIL_ACCOUNT = "edgar1223@163.com";
    /**
     * 授权码:ECCTKZAVPRIQGBBE
     */
    private static final String MY_EMAIL_PASSWORD = "WEVJEYBEJHBKREML";// 密码,是你自己的设置的授权码

    // SMTP服务器(这里用的163 SMTP服务器)
    /**
     * 163代理服务器:smtp.163.com
     */
    private static final String MEAIL_163_SMTP_HOST = "smtp.163.com";
    /**
     * 163 使用的端口:25
     */
    private static final String SMTP_163_PORT = "25";// 端口号,这个是163使用到的;QQ的应该是465或者875
    /**
     * @param targetAddr 目标邮箱地址
     * @param code       验证码
     */
    public static void sendMail(String targetAddr, String code) {
        Properties p = new Properties();
        p.setProperty("mail.smtp.host", MEAIL_163_SMTP_HOST);
        p.setProperty("mail.smtp.port", SMTP_163_PORT);
        p.setProperty("mail.smtp.socketFactory.port", SMTP_163_PORT);
        p.setProperty("mail.smtp.auth", "true");
        p.setProperty("mail.smtp.socketFactory.class", "SSL_FACTORY");

        Session session = Session.getInstance(p, new Authenticator() {
            // 设置认证账户信息
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(MY_EMAIL_ACCOUNT, MY_EMAIL_PASSWORD);
            }
        });
//        session.setDebug(true);
        MimeMessage message = new MimeMessage(session);
        try {
            // 发件人
            message.setFrom(new InternetAddress(MY_EMAIL_ACCOUNT));
            // 收件人和抄送人
            message.setRecipients(Message.RecipientType.TO, targetAddr);

            // 内容(这个内容还不能乱写,有可能会被SMTP拒绝掉;多试几次吧)
            message.setSubject("注册验证码");
            message.setContent("您的验证码为 : <h1>" + code+"</h1>", "text/html;charset=UTF-8");
            message.setSentDate(new Date());
            message.saveChanges();
            Transport.send(message);
        } catch (MessagingException e) {
            e.printStackTrace();
        }

    }
}

FormatUtil格式类

package cn.tedu.kawasaki.utils;

import java.util.regex.Pattern;

public class FormatUtil {
    /**
     * 正则表达式:验证用户名
     */
    private static final String REGEX_USERNAME = "^[a-zA-Z]\\w{5,20}$";

    /**
     * 正则表达式:验证密码
     */
    private static final String REGEX_PASSWORD = "^[a-zA-Z0-9]{6,20}$";

    /**
     * 正则表达式:验证手机号
     */
    private static final String REGEX_MOBILE = "^((17[0-9])|(14[0-9])|(13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";

    /**
     * 正则表达式:验证邮箱
     */
    private static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";

    /**
     * 正则表达式:验证汉字
     */
    private static final String REGEX_CHINESE = "^[\u4e00-\u9fa5],{0,}$";

    /**
     * 正则表达式:验证身份证
     */
    private static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)";

    /**
     * 正则表达式:验证URL
     */
    private static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";

    /**
     * 正则表达式:验证IP地址
     */
    private static final String REGEX_IP_ADDR = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)";

    /**
     * 校验用户名
     *
     * @param username
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isUsername(String username) {
        return Pattern.matches(REGEX_USERNAME, username);
    }

    /**
     * 校验密码
     *
     * @param password
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isPassword(String password) {
        return Pattern.matches(REGEX_PASSWORD, password);
    }

    /**
     * 校验手机号
     *
     * @param mobile
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isMobile(String mobile) {
        return Pattern.matches(REGEX_MOBILE, mobile);
    }

    /**
     * 校验邮箱
     *
     * @param email
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isEmail(String email) {
        return Pattern.matches(REGEX_EMAIL, email);
    }

    /**
     * 校验汉字
     *
     * @param chinese
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isChinese(String chinese) {
        return Pattern.matches(REGEX_CHINESE, chinese);
    }

    /**
     * 校验身份证
     *
     * @param idCard
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isIDCard(String idCard) {
        return Pattern.matches(REGEX_ID_CARD, idCard);
    }

    /**
     * 校验URL
     *
     * @param url
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isUrl(String url) {
        return Pattern.matches(REGEX_URL, url);
    }

    /**
     * 校验IP地址
     *
     * @param ipAddr
     * @return
     */
    public static boolean isIPAddr(String ipAddr) {
        return Pattern.matches(REGEX_IP_ADDR, ipAddr);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值