up:: 发送第一封邮件

说明: 本小节我们将去解决两个问题。第一个问题是加上一个校验码,这个是随机生成的,第二个是我们想阻止那些别有用心的人,他们反复的去调用我们发送邮件的接口,我们在一段时间内只允许给同一个邮箱发送一次邮件就是这两件事情。

生成随机校验码

上篇博客已开发到发送注册邮件,但是没有开发验证码的生成,具体参考上篇博客发送第一封邮件

1. 打开EmailUtils,开发生成验证码

 
public static String genVerificationCode() {
    List<String> verificationChars = Arrays.asList(
            new String[]{"0", "1", "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"});
    Collections.shuffle(verificationChars);
    String result = "";
    for (int i = 0; i < 6; i++) {
        result += verificationChars.get(i);
    }
    return result;
}
  //测试验证码生成没有
public static void main(String[] args) {
    System.out.println(EmailUtil.genVerificationCode());
}

运行测试:

验证码存储到Redis

我们在本小节最开始也讲过,我们需要呢去防止恶意用户去反复的发邮件,那我们防止的方法呢,就是把这个邮件地址以及他对应的验证码放到我们的 radis中去,这样主要有两点好处,第一点呢是我们可以利用它的一个过期时间的能力,保证用户在一段时间之内他没有办法重发,当然,过了这个过期时间之后,我们还是允许用户重发的。因为有的时候呢确实会出现邮件收不到的特殊情况,我们可以让他再发一次。第二个好处呢是说我们没有必要在我们的数据库里,在我们的mysql里没有必要再去加一个字段来保存这个验证码,我们只需要呢,把它保存在 redis 中就可以了,因为这个数据其实对于我们业务而言并没有很大的作用,后期呢也没有必要去再次查询了,像这样临时的数据就比较适合放到 redis 里面去,所以呢,我们去引入 redis

1.pom.xml引入依赖

<dependency>
  <groupId>org.redisson</groupId>
  <artifactId>redisson</artifactId>
  <version>3.13.6</version>
</dependency>

2.EmailServiceImpl.java添加方法将验证码和邮箱保存到Redis

 
@Override
public Boolean saveEmailToRedis(String emailAddress, String verificationCode) {
    RedissonClient client = Redisson.create();
    RBucket<String> bucket = client.getBucket(emailAddress);
    boolean exists = bucket.isExists();
    if (!exists) {
        bucket.set(verificationCode, 60, TimeUnit.SECONDS);
        return true;
    }
    return false;
}

3.记得反向生成方法接口

Boolean saveEmailToRedis(String emailAddress, String verificationCode);

4. 到controller层进行验证码发送

 
/**
 * 发送邮件
 */
@PostMapping("/user/sendEmail")
@ResponseBody
public ApiRestResponse sendEmail(@RequestParam("emailAddress") String emailAddress)
        throws ImoocMallException {
    //检查邮件地址是否有效,检查是否已注册
    boolean validEmailAddress = EmailUtil.isValidEmailAddress(emailAddress);
    if (validEmailAddress) {
        boolean emailPassed = userService.checkEmailRegistered(emailAddress);
        if (!emailPassed) {
            return ApiRestResponse.error(ImoocMallExceptionEnum.EMAIL_ALREADY_BEEN_REGISTERED);
        } else {
            String verificationCode = EmailUtil.genVerificationCode();
            Boolean saveEmailToRedis = emailService.saveEmailToRedis(emailAddress, verificationCode);
            if (saveEmailToRedis) {
                        emailService.sendSimpleMessage(emailAddress, Constant.EMAIL_SUBJECT, "欢迎注册,您的验证码是"
                                + verificationCode);
                return ApiRestResponse.success();
            } else {
                return ApiRestResponse.error(ImoocMallExceptionEnum.EMAIL_ALREADY_BEEN_SEND);
            }
        }
    } else {
        return ApiRestResponse.error(ImoocMallExceptionEnum.WRONG_EMAIL);
    }
}

说明: 1. 其中的Constant常量SUBJECT上篇博客讲过,请及时查阅 2. 抛出错误

验证测试

1.错误邮箱格式测试

2. 邮箱已注册问题测试

像数据库添加自己的邮箱账号:

继续测试:

3. 邮箱验证码存储到redis测试

60s内再点击发送,就会抛出错误

说明:查看键值对

过了60s后再打开就无法打开了,缓存已经清除