登录验证码之QQ邮箱

工具类:实现生成验证码的功能,和实现生成随机数的功能

public class MailUtils {

    // 发送邮件验证码
    public static void sendTestMail(String email, String code) throws MessagingException {
        // 1.创建Properties 类用于记录邮箱的一些属性
        Properties pros = new Properties();
        // 1.1 表示SMTP发送邮件,必须进行身份验证
        pros.put("mail.smtp.auth", "true");
        // 1.2 此处填写SMTP服务器
        pros.put("mail.smtp.host", "smtp.qq.com");
        // 1.3 端口号,QQ邮箱端口587
        pros.put("mail.smtp.port", "587");
        // 1.4 此处填写,写信人的账号
        pros.put("mail.user", "写信人的QQ号(因为我们是自己操作,可以填写自己的)");
        // 1.5 此处填写16位STMP口令  为QQ邮箱授权码
        pros.put("mail.password", "QQ邮箱授权码(在QQ邮箱里面操作弄出来的)");

        // 2.构建授权信息,用于进行SMTP进行身份验证       Authenticator(身份验证器)
        Authenticator authenticator = new Authenticator() {
            protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
                // 2.1 用户名
                String userName = pros.getProperty("mail.user");
                // 2.2 16位STMP口令
                String password = pros.getProperty("mail.password");
                return new javax.mail.PasswordAuthentication(userName, password);
            }
        };

        // 3.使用环境属性和授权信息,创建邮件会话
        Session mailSession = Session.getInstance(pros, authenticator);
        // 4.创建邮件消息对象
        MimeMessage message = new MimeMessage(mailSession);
        // 4.1 设置发件人
        InternetAddress from = new InternetAddress(pros.getProperty("mail.user"));
        message.setFrom(from);
        // 4.2 设置收件人
        InternetAddress to = new InternetAddress(email);
        message.setRecipient(Message.RecipientType.TO, to);
        // 4.3 设置邮件标题
        message.setSubject("【AT瑞吉外卖】邮箱登录验证码");
        // 4.4 设置邮件的正文
        message.setContent("尊敬的AT用户:您好!\r\n您的登录验证码为:" + code + "(有效期为一分钟,请勿告知他人)", "text/html;charset=UTF-8");

        // 5.最后,发送邮件
        Transport.send(message);
    }

    // 获取六位随机验证码
    public static String getCode() {
        // 由于数字 1 、 0 和字母 O 、l 有时分不清楚,所以,没有数字 1 、 0
        String[] beforeShuffle = {"2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F",
                "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a",
                "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
                "w", "x", "y", "z"};
        // 将数组转换成集合
        List<String> list = Arrays.asList(beforeShuffle);
        // 打乱集合顺序,以达到随机的效果
        Collections.shuffle(list);
        // 创建StringBuilder,不是线程安全的,但是速度比StringBuffer更快
        StringBuilder sb = new StringBuilder();
        // 将集合转变成StringBuilder字符串
        for (String s : list) {
            sb.append(s);
        }
        // 返回sb字符串中第10~17位的5位验证码,这个区间其实随便设的
        return sb.substring(10, 16);
    }
}

UserController:

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;

    // 发送邮箱验证码
    @PostMapping("/sendMsg")
    public R<String> sendMsg(@RequestBody User user, HttpSession session) throws MessagingException {
        if (userService.sendMsg(user, session)) {
            return R.success("验证码发送成功");
        }
        return R.error("验证码发送失败");
    }

    // 移动端用户登录登录
    @PostMapping("/login")
    public R<User> login(@RequestBody Map<String, String> map, HttpSession session) {
        User user = userService.login(map, session);
        return R.success(user);
    }
}

userService:

public interface UserService extends IService<User> {

    // 发送邮箱验证码
    Boolean sendMsg(User user, HttpSession session) throws MessagingException;

    // 移动端用户登录
    User login(Map<String, String> map, HttpSession session);


}

userServiceImpl:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    // 发送邮箱验证码
    @Override
    public Boolean sendMsg(User user, HttpSession session) throws MessagingException {
        // 1.获取前端传来的用户邮箱
        String email = user.getEmail();
        // 2.如果邮箱不为空才进行下一步操作
        if (!email.isEmpty()) {
            // 2.1 随机生成六位数验证码
            String code = MailUtils.getCode();
            // 2.2 发送验证码邮件
            MailUtils.sendTestMail(email, code);
            // 2.3 把获得的验证码存入session保存作用域,方便后面拿出来比对(code,就是上面生成的6位随机数验证码,这里的email仅仅是一个存在session域中的名字
            session.setAttribute(email, code);

            // 启动多线程来限定验证码的时效性
            new Thread(() -> {
                try {
                    // 验证码的有效时长
                    Thread.sleep(60000L);
                    // 更换新验证码
                    session.setAttribute(email, MailUtils.getCode());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            
            return true;
        }
        return false;
    }

    // 移动端用户登录登录
    @Override
    public User login(Map<String, String> map, HttpSession session) {
        // 获取前端传送来的用户邮箱
        String email = map.get("email");
        // 获取前端传送来的验证码
        String code = map.get("code");
        // 验证邮箱和验证码是否为空,如果为空则直接登录失败
        if (email.isEmpty() || code.isEmpty()) {
            throw new CustomException("邮箱或验证码不能为空");
        }

        // 如果邮箱和验证码不为空,前往调用数据层查询数据库有无该用户
        // 获取之前存在session保存作用域中的正确验证码
        String trueCode = (String) session.getAttribute(email);

        // 比对用户输入的验证码和真实验证码,错了直接登录失败
        if (!code.equals(trueCode)) {
            throw new CustomException("验证码错误");
        }

        // 验证码匹配,开始调用数据库查询
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getEmail, email);
        User user = this.getOne(lqw);

        // 如果数据库中没有该用户,就是新用户,要添加新用户
        if (user == null) {
            // 添加新用户
            user = new User();
            user.setEmail(email);
            this.save(user);
        }
        // 最后把这个登录用户存到session保存作用域中,表示已登录,让拦截器放行
        session.setAttribute("user", user.getId());
        return user;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡布斯特雷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值