1、最近开发一个系统,有个需求就是,忘记密码后通过邮箱找回。现在的系统在注册的时候都会强制输入邮箱,其一目的就是 通过邮件绑定找回,可以进行密码找回。通过java发送邮件的功能我就不说了,重点讲找回密码。

2、参考别人的思路:发送邮件→请求邮件里的URL→验证url→{验证成功修改密码,不成功跳转到失败页面}

重点就是如何生成这个url和如何解析这个url. 
需要注意的是一个url只能修改一次密码,当同一帐号发送多封邮件,只有最后一封邮件的url

3、加密能防止伪造攻击,一次url只能验证一次,并且绑定了用户。生成url: 可以用UUID生成随机密钥。

数字签名 = MD5(用户名+'$'+过期时间+‘$’+密钥key) 
数据库字段(用户名(主键),密钥key,过期时间) 
url参数(用户名,数字签名) ,密钥key的生成:在每一个用户找回密码时候为这个用户生成一个密钥key ,

url example: http://localhost:8080/user/reset_password?sid=D622D6A23FBF86FFE696B593D55351A54AEAEA77&userName=test4

生成过期时间,生成数字签名,生成url,发送邮件. saveOrUpdate(用户名,密钥key,过期时间)

以下为springMvc代码

  1. @RequestMapping(value = "/user/i_forget_password")
  2. @ResponseBody
  3. public Map forgetPass(HttpServletRequest request,String userName){
  4. Users users = userService.findUserByName(userName);
  5. Map map = new HashMap<String ,String >();
  6. String msg = "";
  7. if(users == null){ //用户名不存在
  8. msg = "用户名不存在,你不会忘记用户名了吧?";
  9. map.put("msg",msg);
  10. return map;
  11. }
  12. try{
  13. String secretKey= UUID.randomUUID().toString(); //密钥
  14. Timestamp outDate = new Timestamp(System.currentTimeMillis()+30*60*1000);//30分钟后过期
  15. long date = outDate.getTime()/1000*1000; //忽略毫秒数
  16. users.setValidataCode(secretKey);
  17. users.setRegisterDate(outDate);
  18. userService.update(users); //保存到数据库
  19. String key = users.getUserName()+"$"+date+"$"+secretKey;
  20. String digitalSignature = MD5.MD5Encode(key); //数字签名
  21.  
  22. String emailTitle = "有方云密码找回";
  23. String path = request.getContextPath();
  24. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
  25. String resetPassHref = basePath+"user/reset_password?sid="+digitalSignature+"&userName="+users.getUserName();
  26. String emailContent = "请勿回复本邮件.点击下面的链接,重设密码<br/><a href="+resetPassHref +" target='_BLANK'>点击我重新设置密码</a>" +
  27. "<br/>tips:本邮件超过30分钟,链接将会失效,需要重新申请'找回密码'"+key+"\t"+digitalSignature;
  28. System.out.print(resetPassHref);
  29. SendMail.getInstatnce().sendHtmlMail(emailTitle,emailContent,users.getEmail());
  30. msg = "操作成功,已经发送找回密码链接到您邮箱。请在30分钟内重置密码";
  31. logInfo(request,userName,"申请找回密码");
  32. }catch (Exception e){
  33. e.printStackTrace();
  34. msg="邮箱不存在?未知错误,联系管理员吧。";
  35. }
  36. map.put("msg",msg);
  37. return map;
  38. }

找回链接已经发到邮箱了。进入邮箱点开链接

以下为链接检验代码,验证通过 跳转到修改密码界面,否则跳转到失败界面

  1. @RequestMapping(value = "/user/reset_password",method = RequestMethod.GET)
  2. public ModelAndView checkResetLink(String sid,String userName){
  3. ModelAndView model = new ModelAndView("error");
  4. String msg = "";
  5. if(sid.equals("") || userName.equals("")){
  6. msg="链接不完整,请重新生成";
  7. model.addObject("msg",msg) ;
  8. logInfo(userName,"找回密码链接失效");
  9. return model;
  10. }
  11. Users users = userService.findUserByName(userName);
  12. if(users == null){
  13. msg = "链接错误,无法找到匹配用户,请重新申请找回密码.";
  14. model.addObject("msg",msg) ;
  15. logInfo(userName,"找回密码链接失效");
  16. return model;
  17. }
  18. Timestamp outDate = users.getRegisterDate();
  19. if(outDate.getTime() <= System.currentTimeMillis()){ //表示已经过期
  20. msg = "链接已经过期,请重新申请找回密码.";
  21. model.addObject("msg",msg) ;
  22. logInfo(userName,"找回密码链接失效");
  23. return model;
  24. }
  25. String key = users.getUserName()+"$"+outDate.getTime()/1000*1000+"$"+users.getValidataCode(); //数字签名
  26. String digitalSignature = MD5.MD5Encode(key);
  27. System.out.println(key+"\t"+digitalSignature);
  28. if(!digitalSignature.equals(sid)) {
  29. msg = "链接不正确,是否已经过期了?重新申请吧";
  30. model.addObject("msg",msg) ;
  31. logInfo(userName,"找回密码链接失效");
  32. return model;
  33. }
  34. model.setViewName("user/reset_password"); //返回到修改密码的界面
  35. model.addObject("userName",userName);
  36. return model;
  37. }

补充1:Timestamp类型对象在保存到数据的时候 毫秒精度会丢失。比如:2013-10-08 10:29:10.234 存到mysql数据库的时候 变成 2013-10-08 10:29:10.0。时间变得不相同了,sid 匹配的时候不会相等。 所以我做了忽略精度的操作。

补充2:解决linux下面title中文乱码

  1. sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
  2. mailMessage.setSubject(MimeUtility.encodeText(mailInfo.getSubject(), "UTF-8", "B")); //解决linux邮件title乱码

补充3:怎么不直接把sid插入到user表呢。验证的时候直接比较sid就ok了。

SpringMVC通过邮件找回密码功能的实现的更多相关文章

  1. javaWeb实现使用邮箱邮件找回密码功能

    JSP+Jmail+JavaBean 发邮件(转)2010-08-23 18:052007年04月14日 14:32/* * SendMail.java * * Created on 2007年3月3 ...

  2. 通过邮件找回密码功能的Java实现

    1.有个需求就是,忘记密码后通过邮箱找回.现在的系统在注册的时候都会强制输入邮箱,其一目的就是 通过邮件绑定找回,可以进行密码找回.通过java发送邮件的功能我就不说了,重点讲找回密码. 2.参考别人 ...

  3. PHP会员找回密码功能实现实例介绍

    设置思路 1.用户注册时需要提供一个E-MAIL邮箱,目的就是用该邮箱找回密码. 2.当用户忘记密码或用户名时,点击登录页面的“找回密码”超链接,打开表单,并输入注册用的E-MAIL邮箱,提交. 3. ...

  4. Jsp邮件找回密码全攻略

    [来源网络  http://www.2cto.com/kf/201502/376374.html] 一般大型网站我们登录的时候,密码忘了都有个功能可以找回密码. 细数下大致的方法: 1.直接把密码发送 ...

  5. 【JavaWeb】通过邮件找回密码

    前言 本文将介绍忘记密码时通过发送重置密码邮件找回密码的实现思路.整个实现过程中最重要的就是以下三点: 如何发送邮件到用户指定邮箱 邮件中的重置密码链接构成是怎么样的 验证重置密码链接的合法性(是否过 ...

  6. PHP会员找回密码功能的简单实现

    文章来自:博客 http://www.jb51.net/article/91944.htm 设置思路 1.用户注册时需要提供一个E-MAIL邮箱,目的就是用该邮箱找回密码. 2.当用户忘记密码或用户名 ...

  7. spring mvc下实现通过邮箱找回密码功能

    1功能分析 通过spring mvc框架实现通过邮箱找回密码. 2 实现分析 主要是借助某个邮箱的pop3/smtp服务实现的邮件代发功能. 3 源码分析 3.1首先在用户表对应的javabean中加 ...

  8. php邮箱找回密码功能

    原理很简单: 用户找回密码的时候,填写用户名,程序得到用户名便可以去数据库取出用户对应的密码以及当时填写的邮箱, 根据用户名和密码生成一个key=md5(username+password),然后$s ...

  9. django项目中使用邮箱找回密码功能

    本文使用qq邮箱,需要登录邮箱,在设置-账户里面开启SMTP服务,要记下授权码 前端html {#找回密码的表单#} <form action="" method=" ...

随机推荐

  1. 关于List Map Set的线程安全的问题

    常见的ArrayList  LinkedList  HashMap TreeMap LinkedHashMap HashSet TreeSet LinkedHashSet 都是线程不安全的.如果要使用 ...

  2. Java Log Viewer日志查看器

    工欲善其事必先利其器 在投奔怒海--一个Domino老程序猿眼里的Java开发我提到眼下所做的Java开发中遇到的大量日志之问题. server控制台刷屏似地滚动,日志文件飞快地增长,debug的时候 ...

  3. How To Backup Your Android Phone’s Boot, Recovery And System Partition Images -- RomDump

    One can’t stress enough on the importance of backups and when it comes to tinkering with your Androi ...

  4. Tasker to detect application running in background

    We used to be told that tasker is only capable of detecting foreground application, if the app gets ...

  5. CSS Flex布局属性整理

    Flex布局 display: flex; 将对象作为弹性伸缩盒展示,用于块级元素 display: inline-flex; 将对象作为弹性伸缩盒展示,用于行内元素 注意兼容问题: webkit内核 ...

  6. C#监控文件夹变化

    当需要监控某一文件,FileSystemWatcher类提供了Created, Deleted,Rename等事件. 就拿FileSystemWatcher的Created事件来说,该事件类型是Fil ...

  7. maven切换到阿里云镜像

    maven默认去中央仓库下载jar速度奇慢,切换成阿里的镜像源会快很多 maven  settings.xml配置 <?xml version="1.0" encoding= ...

  8. 张明楷:案件事实认定方法的七点注意 z

    作者|张明楷 来源|<法学杂志> 大体而言,定罪是一个三段论的推理过程.刑法规范是大前提,案件事实是小前提,如果二者相符合,便可以作出相应的判决.具体地说,法官必须把应当判决的.具体的个案 ...

  9. dao层的泛型实现(2种方法)

    一: package com.wzs.test2.dao; import java.util.List; public interface CommonDAO { public <T> v ...

  10. Jquery Mobile实例--利用优酷JSON接口读取视频数据

    本文将介绍,如何利用JqueryMobile调用优酷API JSON接口显示视频数据. (1)注册用户接口. 首页,到 http://open.youku.com 注册一个账户,并通过验证.然后找到A ...