spring mvc 密碼找回功能
阿新 • • 發佈:2022-05-23
一、傳送郵件
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,"密碼修改成功"); }