-
Notifications
You must be signed in to change notification settings - Fork 197
13.邮箱验证码发送实现
JustCoding-Hai edited this page Nov 8, 2020
·
1 revision
1.首先在自己的qq邮箱中开启POP3/SMTP服务.获取到授权码。相当于发送方的密码。
QQ邮箱登录页面地址
2.添加依赖包spring-boot-starter-mail
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
3.在appication.properties中配置邮件发送服务信息。
#SMTP服务器地址
spring.mail.host=smtp.qq.com
#SMTP服务器端口
spring.main.port=587
#发送者的用户名(邮箱)
spring.mail.username[email protected]
#发送方的授权码
spring.mail.password=#申请得到的授权码
#编码格式
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
#debug,输出邮件发送的过程
spring.mail.properties.mail.debug=true
4.测试发送简单的邮件
//测试邮件发送
@Test
void test03(){
SimpleMailMessage msg=new SimpleMailMessage();
//邮件的主题
msg.setSubject("这是测试邮件主题");
//邮件的内容
msg.setText("这是测试邮件内容:\nsecond try");
//邮件的发送方,对应配置文件中的spring.mail.username
msg.setFrom("[email protected]");
//邮件发送时间
msg.setSentDate(new Date());
//邮件接收方
msg.setTo("[email protected]");
//执行发送
javaMailSender.send(msg);
}
5.登录邮箱验证码实现,管理端的登录页面获取验证码的接口代码如下:
/**
* @author Hai
* @date 2020/6/16 - 17:33
*/
@RestController
public class LoginController {
/**
* 获取验证码图片写到响应的输出流中,保存验证码到session
* @param response
* @param session
* @throws IOException
*/
@GetMapping("/verifyCode")
public void getVerifyCode(HttpServletResponse response, HttpSession session) throws IOException {
VerificationCode code = new VerificationCode();
BufferedImage image = code.getImage();
String text = code.getText();
session.setAttribute("verify_code",text);
VerificationCode.output(image,response.getOutputStream());
}
@Autowired
JavaMailSender javaMailSender;
/**
* 获取邮箱验证码,并保存到本次会话
* @param session
*/
@GetMapping("/admin/mailVerifyCode")
public RespBean getMailVerifyCode(HttpSession session){
//获取随机的四个数字
StringBuilder code=new StringBuilder();
for (int i = 0; i <4; i++) {
code.append(new Random().nextInt(10));
}
//邮件内容
SimpleMailMessage msg = new SimpleMailMessage();
msg.setSubject("微言聊天室管理端验证码验证");
msg.setText("本次登录的验证码:"+code);
msg.setFrom("[email protected]");
msg.setSentDate(new Date());
msg.setTo("[email protected]");
//保存验证码到本次会话
session.setAttribute("mail_verify_code",code.toString());
//发送到邮箱
try {
javaMailSender.send(msg);
return RespBean.ok("验证码已发送到邮箱,请注意查看!");
}catch (Exception e){
e.printStackTrace();
return RespBean.error("服务器出错啦!请稍后重试!");
}
}
}
客户端界面发送“/admin/mailVerifyCode”请求,即发送随机的4位验证码到特定的邮箱中,并且把这四位验证码添加到当前请求会话(session)中。
6.配置Filter过滤器,拦截前端发来的登录管理端的请求,请判断请求中的参数“code”和会话中保存的“mail_verify_code”是否相等,相等就通过请求进行用户名和密码验证,否则直接返回。
/**
* 拦截登录请求,验证输入的验证码是否正确
* @author Hai
* @date 2020/5/28 - 17:31
*/
@Component
public class VerificationCodeFilter extends GenericFilter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//如果是登录请求则拦截
if ("POST".equals(request.getMethod())&&"/doLogin".equals(request.getServletPath())){
//用户输入的验证码
String code = request.getParameter("code");
//session中保存的验证码
String verify_code = (String) request.getSession().getAttribute("verify_code");
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
//验证session中保存是否存在
try {
//验证是否相同
if (!code.toLowerCase().equals(verify_code.toLowerCase())){
//输出json
writer.write(new ObjectMapper().writeValueAsString( RespBean.error("验证码错误!")));
return;
}else {
filterChain.doFilter(request,response);
}
}catch (NullPointerException e){
writer.write(new ObjectMapper().writeValueAsString(RespBean.error("请求异常,请重新请求!")));
}finally {
writer.flush();
writer.close();
}
}
//管理端登录请求
else if ("POST".equals(request.getMethod())&&"/admin/doLogin".equals(request.getServletPath())){
//获取输入的验证码
String mailCode = request.getParameter("mailCode");
//获取session中保存的验证码
String verifyCode = ((String) request.getSession().getAttribute("mail_verify_code"));
//构建响应输出流
response.setContentType("application/json;charset=utf-8");
PrintWriter printWriter =response.getWriter();
try {
if(!mailCode.equals(verifyCode)){
printWriter.write(new ObjectMapper().writeValueAsString(RespBean.error("验证码错误!")));
}else {
filterChain.doFilter(request,response);
}
}catch (NullPointerException e){
printWriter.write(new ObjectMapper().writeValueAsString(RespBean.error("请求异常,请重新请求!")));
}finally {
printWriter.flush();
printWriter.close();
}
}
else {
filterChain.doFilter(request,response);
}
}
}
7.在Spring Security中的配置类MultiHttpSecurityConfig中通过以下代码,用于过滤每一次请求。
//将验证码过滤器添加在用户名密码过滤器的前面
http.addFilterBefore(verificationCodeFilter, UsernamePasswordAuthenticationFilter.class);