在做注册账号、找回账号密码和修改密码的时候,通常要先向指定用户邮箱发送验证码,再让用户带着验证码去做以上操作。
在Springboot中想要完成这个功能,有一个很方便的组件Java Mail Sender。可以在初始化项目的时候勾选,也可以后期在Maven中导入坐标。
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
依赖之后,可以去application.yml中配置邮箱相关的属性,账号密码等。
配置文件(163为例)
spring:
mail:
host: smtp.163.com
username: XXXX@163.com
password: 授权码(非密码)
default-encoding: UTF-8
做好上述准备之后,就可以开始写功能了。由于只是演示向指定邮箱发送验证码并验证用户输入的验证码功能,就不写Dao层了。
首先从Service层开始写
Sevice
@Service
public class emailService {
private Integer code;
@Value("${spring.mail.username}")
private String from="";
@Autowired
private JavaMailSender javaMailSender;
public String email(String to) {
code = RandomUtil.randomInt(100000, 999999);
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(from);
simpleMailMessage.setTo(to);
simpleMailMessage.setSubject("test");
simpleMailMessage.setText("Code:" + code.toString());
javaMailSender.send(simpleMailMessage);
return code.toString();
}
}
其中code的生成用了Hutool组件,节省一些基本逻辑的编写。 由于只是发送验证码(字符串),而没有发送附件,所以这里用到的只是simpleMailMessage。
对于这个对象,我们要传入必要的参数有(to ,from ,subject ,text )对应的是(收件者,发送者,主题,内容)。其中from是最重要的,一般直接从配置文件中取,或者直接写死,如果from对应的邮箱没有在配置文件中配置过,则会报错。
报错:
javax.mail.internet.AddressException: Illegal address
to则是从请求中直接拿的,也就是从Controller层中拿的,或者说是用户输入的。而subject一般是写死的,当然,也可以跟text一样在Service层动态生成。其中text的验证码部分用到了hutool组件。当然验证码也可以自己编写逻辑。如果想用Hutool则导入依赖。
Maven
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.3</version>
</dependency>
接下来编写Controller层
Controller
@RestController
public class register {
@Autowired
private emailService emailService;
@GetMapping("/register")
public String sendCode(String to, HttpSession httpSession) {
String randomCode= emailService.email(to);
httpSession.setAttribute("code", randomCode);
return "验证码已发送到指定邮箱" + randomCode;
}
@GetMapping("/checkCode")
public String checkCode(String code, HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return "验证码未发送";
}
String Code = (String) session.getAttribute("code");
if (code.equals(Code)) {
return "验证码正确";
}
return "验证码错误";
}
}
Controller层一共写了两个方法:发验证码,检查验证码。
Controller层中关键的部分是Session,注册的时候直接向容器要一个HttpSession并向Session中写入验证码即可。
而检查验证码的时候应该是从容器里要一个HttpServletRequest,再从request中获取一个session,关键的地方是要传入一个false。
获取session
HttpSession session = request.getSession(false);
这个false的意思是,如果之前有一个session则返回该session,如果没有则返回空指针。这样就避免了未发送验证码就直接去检查验证码而直接开辟了一个session,减少内存的开销。
这里有一个技巧:如果要向Session中存数据,则可以直接问容器要一个session或者用request获取一个session时填true(不填默认就是true)。(建议直接问容器要)
HttpSession session = request.getSession(true);
如果只是从session中取数据(不写入)那么就不要创建新的session。
注意,如果传入了false要做空指针判断。
源代码可私信或评论留言。