spring mvc下实现通过邮箱找回密码功能
1功能分析
通过spring mvc框架实现通过邮箱找回密码。
2 实现分析
主要是借助某个邮箱的pop3/smtp服务实现的邮件代发功能。
3 源码分析
3.1首先在用户表对应的javabean中加入两个字段outdate和validatecode用于验证数字签名。
private String validatacode; private Date outdate; @Column(name = "validatacode", length = 50) public String getValidatacode() { return validatacode; } public void setValidatacode(String validatacode) { this.validatacode = validatacode; } @Column(name = "outdate", length = 50) public Date getOutdate() { return outdate; } public void setOutdate(Date outdate) { this.outdate = outdate; }
3.2发送邮件工具类
package util; import java.security.GeneralSecurityException; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import com.sun.mail.util.MailSSLSocketFactory; public class SendmailUtil { // 设置服务器 private static String KEY_SMTP = "mail.smtp.host"; private static String VALUE_SMTP = "smtp.163.com";//邮箱服务器地址 // 服务器验证 private static String KEY_PROPS = "mail.smtp.auth"; private static boolean VALUE_PROPS = true; // 发件人用户名、密码 private String SEND_USER = "填你用来做发送邮件的邮箱"; private String SEND_UNAME = "发件人用户名"; private String SEND_PWD = "*****";//这里是关键,是你开通了pop3/smtp服务以后获得的授权码 // 建立会话 private MimeMessage message; private Session s; /* * 初始化方法 */ public SendmailUtil() throws GeneralSecurityException { Properties props = System.getProperties(); props.setProperty(KEY_SMTP, VALUE_SMTP); props.put(KEY_PROPS, "true"); props.put("mail.smtp.auth", "true"); MailSSLSocketFactory sf = new MailSSLSocketFactory(); sf.setTrustAllHosts(true); props.put("mail.smtp.ssl.enable", "true"); props.put("mail.smtp.ssl.socketFactory", sf); s = Session.getDefaultInstance(props, new Authenticator(){ protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(SEND_UNAME, SEND_PWD); }}); s.setDebug(true); message = new MimeMessage(s); } /** * 发送邮件 * * @param headName * 邮件头文件名 * @param sendHtml * 邮件内容 * @param receiveUser * 收件人地址 */ public void doSendHtmlEmail(String headName, String sendHtml, String receiveUser) { try { // 发件人 InternetAddress from = new InternetAddress(SEND_USER); message.setFrom(from); // 收件人 InternetAddress to = new InternetAddress(receiveUser); message.setRecipient(Message.RecipientType.TO, to); // 邮件标题 message.setSubject(headName); String content = sendHtml.toString(); // 邮件内容,也可以使纯文本"text/plain" message.setContent(content, "text/html;charset=GBK"); message.saveChanges(); Transport transport = s.getTransport("smtp"); // smtp验证,就是你用来发邮件的邮箱用户名密码 transport.connect(VALUE_SMTP, SEND_UNAME, SEND_PWD); // 发送 transport.sendMessage(message, message.getAllRecipients()); transport.close(); System.out.println("send success!"); } catch (AddressException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MessagingException e) { e.printStackTrace(); } } }
3.3 spring mvc发送邮件
首先要有前台页面,填写邮箱或用户名,示例图如下:
jsp页面代码:
<div class="container"> <div class="col-md-12"> <h1 class="margin-bottom-15">重置您的密码</h1> <form class="form-horizontal templatemo-forgot-password-form templatemo-container" role="form" action="javascript:findpwd();" method="post"> <div class="form-group"> <div class="col-md-12"> 请输入邮箱或用户名,点击确定。找回密码链接将发送至您的邮箱 </div> </div> <div class="form-group"> <div class="col-md-12"> <input type="text" class="form-control" id="yhmoryx" placeholder="您的邮箱账号或用户名"> </div> </div> <div class="form-group"> <div class="col-md-12"> <input type="submit" value="确定" class="btn btn-danger"> <br><br> <a href="#">无需重置密码,现在登录?</a> <!--<a href="login-2.html">用户名和注册邮箱已忘记,进行账号申诉?</a>--> </div> </div> </form> </div> </div>
后台接收请求代码:
@RequestMapping(value = "/user/forgetpwd") @ResponseBody public Map forgetPass(HttpServletRequest request,@RequestParam("yhmoryx") String yhmoryx,Model model){ XtYh xtYh=xtYhService.getXtYhByYhmSjYx(yhmoryx); Map<String, String> map = new HashMap<String ,String >(); String msg = ""; if(yhmoryx.equals("")){ //用户名不存在 msg = "请输入用户名或邮箱!"; map.put("msg",msg); return map; } if(xtYh == null){ //用户不存在 msg = "用户名不存在,你不会忘记用户名了吧?"; map.put("msg",msg); return map; } try{ String secretKey= UUID.randomUUID().toString(); //密钥 Timestamp outDate = new Timestamp(System.currentTimeMillis()+30*60*1000);//30分钟后过期 long date = outDate.getTime()/1000*1000; //忽略毫秒数 xtYh.setValidatacode(secretKey); xtYh.setOutdate(outDate); xtYhService.updateXtYh(xtYh); //保存到数据库 String key = xtYh.getYhm()+"$"+date+"$"+secretKey; String digitalSignature = Md5.MD5Encode(key); //数字签名 String emailTitle = "密码找回"; String path = request.getContextPath(); String localstr=request.getLocalAddr(); System.out.println(localstr); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; String resetPassHref = basePath+"resetpassword/user/resetpassword?sid="+digitalSignature+"&yhm="+xtYh.getYhm(); String emailContent = "请勿回复本邮件.点击下面的链接,重设密码<br/><a href="+resetPassHref +" target='_BLANK'>点击我重新设置密码</a>" + "<br/>tips:本邮件超过30分钟,链接将会失效,需要重新申请'找回密码'"+"<br/>tips:本链接可能被邮箱拦截,如链接无效,请复制下列链接到您的浏览器中。<br/>"+ "链接开始:<span style='color:#F00; font-weight:bold'>"+resetPassHref+"<span>链接结束"; // SendmailUtil.class.newInstance().doSendHtmlEmail(emailTitle,emailContent,xtYh.getYx());//调用工具类里面的发送发放 msg = "操作成功,已经发送找回密码链接到您邮箱。请在30分钟内重置密码"; }catch (Exception e){ e.printStackTrace(); msg="邮箱不存在?"; } map.put("msg",msg); return map; }
3.4 发送邮件以后用户点击链接(即上述的resetPassHref)再转到服务器上spring mvc的控制器部分,根据发回来的用户名和数字签名进行处理。
确定以后会执行发送邮件功能,邮箱中接收到的信件如下:
点击链接,会将请求发送到下面的控制器中进行处理:
@RequestMapping(value = "/user/resetpassword",method = RequestMethod.GET) public String checkResetLink(@RequestParam("sid") String sid,@RequestParam("yhm")String yhm,Model model){ System.out.println(sid+yhm); String msg = ""; if(sid.equals("") || yhm.equals("")){ msg="链接不完整,请重新生成"; model.addAttribute("msg",msg); return "findPwdError"; } XtYh xtYh=xtYhService.getXtYhByYhm(yhm); if(xtYh == null){ msg = "链接错误,无法找到匹配用户,请重新申请找回密码."; model.addAttribute("msg",msg) ; return "findPwdError"; } Date outDate = xtYh.getOutdate(); if(outDate.getTime() <= System.currentTimeMillis()){ //表示已经过期 msg = "链接已经过期,请重新申请找回密码."; model.addAttribute("msg",msg) ; return "findPwdError"; } String key = xtYh.getYhm()+"$"+outDate.getTime()/1000*1000+"$"+xtYh.getValidatacode(); //数字签名 String digitalSignature = Md5.MD5Encode(key); System.out.println(key+"\t"+digitalSignature); if(!digitalSignature.equals(sid)) { msg = "链接不正确,是否已经过期了?重新申请吧"; model.addAttribute("msg",msg); return "findPwdError"; } model.addAttribute("userName",yhm); return "resetpage"; }
4 再写一个update用户的操作。在上一步把用户的用户名(或id)传到前台页面,写一个input隐藏域。用户更改完以后点击确定,再把值传到后台,写入数据库。
以下是点击链接以后的页面
填入新密码,点击确定,跳转到登录界面
【注:】参考至其他大神的博客。具体地址没记,去搜狗一下应该能找到