spring mvc 密码找回功能
一、发送邮件
Sprin提供了一个强大方便的邮件API,简化了发送邮件的工作,可以发送富文本邮件,添加附件,使用模板渲染邮件内容。
1. 首先引入需要的jar包
<dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>5.3.17</version> </dependency>
2. 配置邮件发送器
Spring邮件API的核心是
MailSender接口,Spring自带JavaMailSenderImpl实现了MailSender接口,所以需要将JavaMailSenderImpl装配到Bean中。mail.properties
#邮件发送配置 #服务器主机名 smtp.xx.com mail.smtp.host=smtp.163.com mail.smtp.port=25 mail.smtp.username=用户名 #客户端授权码 mail.smtp.password=客户端授权码 #编码字符 mail.smtp.defaultEncoding=utf-8 #是否进行用户名密码校验 mail.smtp.auth= true #设置超时时间 mail.smtp.timeout=20000
spring-context.xml
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="${mail.smtp.host}"/> <property name="port" value="${mail.smtp.port}"/> <property name="username" value="${mail.smtp.username}"/> <property name="password" value="${mail.smtp.password}"/> <property name="defaultEncoding" value="${mail.smtp.defaultEncoding}"/> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">${mail.smtp.auth}</prop> <prop key="mail.smtp.ssl.timeout">${mail.smtp.timeout}</prop> <prop key="mail.smtp.socketFactory.port">${mail.smtp.port}</prop> <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> <prop key="mail.smtp.ssl.trust">${mail.smtp.host}</prop> <prop key="mail.smtp.ssl.protocols">TLSv1.2</prop> <prop key="mail.smtp.starttls.enable">true</prop> <prop key="mail.smtp.starttls.required">true</prop> <prop key="mail.smtp.port">${mail.smtp.port}</prop> <prop key="mail.debug">true</prop> </props> </property> </bean>
注意:需要在邮箱的设置中开启SMTP服务
3. service层实现发送邮件
@Override public boolean sendEmail(String recipient, String subject, String content) { MimeMessage mimeMessage = mailSender.createMimeMessage(); try { MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); /** 发件人的邮箱地址 */ messageHelper.setFrom(emailFrom); /** 收件人邮箱地址 */ messageHelper.setTo(recipient); /** 主题 */ messageHelper.setSubject(subject); /** 内容 * true代表支持html格式*/ messageHelper.setText(content, true); mailSender.send(mimeMessage); return true; } catch (MessagingException e) { return false; } }
二、密码找回
1. 向用户邮箱发送重置密码链接
生成一个30分钟有效的令牌,将过期时间和令牌存入数据库(也可以存到缓存中)
public String forgotPassword(HttpServletRequest request,String email) throws CustomException { User user = userService.getUserByEmail(email); if(user == null){ throw new CustomException("该邮箱未注册"); } try { String secretKey= UUID.randomUUID().toString(); LocalDateTime outDate = LocalDateTime.now().plusMinutes(30); long date = outDate.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()/1000*1000; String key = user.getName()+"$"+date+"$"+secretKey; String digitalSignature = new SimpleHash("MD5",key).toString(); //保存到数据库 user.setRegisterDate(outDate); user.setSid(digitalSignature); userService.update(user); String emailTitle = "密码找回"; String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; String resetPassHref = basePath+"admin/user/reset_password?sid="+digitalSignature+"&email="+email; String emailContent = "请勿回复本邮件.点击下面的链接,重设密码<br/><a href="+resetPassHref +" target='_BLANK'>点击我重新设置密码</a>" + "<br/>tips:本邮件超过30分钟,链接将会失效,需要重新申请'找回密码'" + "<br/>tips:本链接可能被邮箱拦截,如链接无效,请复制下列链接到您的浏览器中。<br/>"+ "链接开始:<span style='color:#F00; font-weight:bold'>"+resetPassHref+"<span>链接结束"; System.out.print(resetPassHref); String msg = "操作成功,已经发送找回密码链接到您邮箱。请在30分钟内重置密码"; // userService.sendEmail(email, emailTitle, emailContent); logger.info(msg); return "admin/forgot/sent"; }catch (Exception e){ throw new CustomException("未知错误,联系管理员吧。"); } }
2. 点击邮件中的链接,进入校验链接的方法
@RequestMapping(value = "/reset_password",method = RequestMethod.GET) public String resetPassword(HttpServletRequest request,String sid,String email) throws CustomException { String msg=""; if(sid.equals("") || email.equals("")){ msg="链接不完整,请重新生成"; throw new CustomException(msg); } User user = userService.getUserByEmail(email); if(user == null){ msg = "链接错误,无法找到匹配用户,请重新申请找回密码."; throw new CustomException(msg); } LocalDateTime outDate = user.getRegisterDate(); //已经过期 if(outDate.toInstant(ZoneOffset.ofHours(8)).toEpochMilli() <= System.currentTimeMillis()){ msg = "链接已经过期,请重新申请找回密码."; throw new CustomException(msg); } if(!user.getSid().equals(sid)) { msg = "链接不正确,是否已经过期了?重新申请吧"; throw new CustomException(msg); } request.setAttribute("id",user.getId()); return "admin/forgot/reset"; }
3. 验证通过后返回修改密码的页面,隐藏域中放userId
4. 提交修改密码
@RequestMapping(value = "/reset_password",method = RequestMethod.POST) @ResponseBody public Result resetPassword(Long id,String new1,String new2) throws CustomException { if(!new1.equals(new2)){ return PageResultUtil.error(500,"两次输入不一致"); } userService.resetPassword(id,new1); return PageResultUtil.success(200,"密码修改成功"); }

浙公网安备 33010602011771号