Java实现邮箱找回密码实例代码

作者:智慧云端日记 时间:2022-01-12 11:48:57 

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

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

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

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

数字签名 = MD5(用户名+'′+过期时间+‘′+过期时间+‘'+密钥key)

数据库字段(用户名(主键),密钥key,过期时间)

url参数(用户名,数字签名) ,密钥key的生成:在每一个用户找回密码时候为这个用户生成一个密钥key ,

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

使用到的数据库如下 :Java实现邮箱找回密码实例代码

找回邮箱密码代码如下:


package com.soq.card.web.action;

import java.sql.Timestamp;
import java.util.List;
import java.util.UUID;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateTemplate;

import com.soq.card.biz.UserHander;
import com.soq.card.entity.Users;
import com.soq.card.tools.DBhepler;
import com.soq.card.tools.Mail;
import com.soq.card.tools.Md5;
import com.soq.card.web.base.BaseAction;

/**
* @author javen
* @Email zyw205@gmail.com
*
*/
public class PassEmailAction extends BaseAction {
 private Users users;
 private UserHander userHander;

private String email;
 private String sid;
 private String userName;

public String sendmail() {
   try {
     HibernateTemplate ht = this.getUserHander().getUsersDAO().getHibernateTemplate();
     SessionFactory factory = ht.getSessionFactory();
     Session session = factory.openSession();
     Criteria criteria = session.createCriteria(Users.class);
     criteria.add(Restrictions.eq("loginName", email));
     List<Users> list = criteria.list();
     if (list.size() > 0) {
       users=list.get(0);
       Mail mail = new Mail();

String secretKey = UUID.randomUUID().toString(); // 密钥
       Timestamp outDate = new Timestamp(System.currentTimeMillis() + 30 * 60 * 1000);// 30分钟后过期
       long date = outDate.getTime() / 1000 * 1000;// 忽略毫秒数 mySql 取出时间是忽略毫秒数的

DBhepler bhepler=new DBhepler();
       String sql="update users set outDate=?,validataCode=? where loginName=?;";
       String str[] ={outDate+"",secretKey,users.getLoginName()};
       bhepler.AddU(sql, str);

//this.getUserHander().getUsersDAO().getHibernateTemplate().update(users); // 保存到数据库
       System.out.println("  UserName>>>> "+users.getUserName());
       String key =users.getUserName() + "$" + date + "$" + secretKey;
       System.out.println(" key>>>"+key);
       String digitalSignature = Md5.md5(key);// 数字签名

String path = this.getRequest().getContextPath();
       String basePath = this.getRequest().getScheme() + "://"
           + this.getRequest().getServerName() + ":"
           + this.getRequest().getServerPort() + path + "/";
       String resetPassHref = basePath + "checkLink?sid="
           + digitalSignature +"&userName="+users.getUserName();
       String emailContent = "请勿回复本邮件.点击下面的链接,重设密码<br/><a href="
           + resetPassHref + " target='_BLANK'>" + resetPassHref
           + "</a> 或者  <a href=" + resetPassHref
           + " target='_BLANK'>点击我重新设置密码</a>"
           + "<br/>tips:本邮件超过30分钟,链接将会失效,需要重新申请'找回密码'" + key
           + "\t" + digitalSignature;

mail.setTo(email);
       mail.setFrom("XX");// 你的邮箱
       mail.setHost("smtp.163.com");
       mail.setUsername("XXX@163.com");// 用户
       mail.setPassword("CXXX");// 密码
       mail.setSubject("[二维码名片]找回您的账户密码");
       mail.setContent(emailContent);
       if (mail.sendMail()) {
         System.out.println(" 发送成功");
         this.getRequest().setAttribute("mesg", "重置密码邮件已经发送,请登陆邮箱进行重置!");
         return "sendMail";
       }
     } else {
       this.getRequest().setAttribute("mesg", "用户名不存在,你不会忘记邮箱了吧?");
       return "noUser";
     }
   } catch (Exception e) {
     // TODO: handle exception
     e.printStackTrace();
   }
   return null;
 }

public String checkResetLink() {
   System.out.println("sid>>>" + sid);

if (sid.equals("") || userName.equals("")) {
     this.getRequest().setAttribute("mesg", "链接不完整,请重新生成");
     System.out.println(">>>>> null");
     return "error";
   }
   HibernateTemplate ht = this.getUserHander().getUsersDAO().getHibernateTemplate();
   SessionFactory factory = ht.getSessionFactory();
   Session session = factory.openSession();
   Criteria criteria = session.createCriteria(Users.class);
   criteria.add(Restrictions.eq("userName", userName));
   List<Users> list = criteria.list();
   if (list.size()>0) {
     users=list.get(0);

Timestamp outDate = (Timestamp) users.getOutDate();
     System.out.println("outDate>>>"+outDate);
      if(outDate.getTime() <= System.currentTimeMillis()){ //表示已经过期
        this.getRequest().setAttribute("mesg", "链接已经过期,请重新申请找回密码.");
        System.out.println("时间 超时");
        return "error";
      }

String key = users.getUserName()+"$"+outDate.getTime()/1000*1000+"$"+users.getValidataCode();//数字签名

System.out.println("key link》》"+key);
      String digitalSignature = Md5.md5(key);// 数字签名

System.out.println("digitalSignature>>>>"+digitalSignature);
      if(!digitalSignature.equals(sid)) {
        this.getRequest().setAttribute("mesg", "链接不正确,是否已经过期了?重新申请吧.");
          System.out.println("标示不正确");
         return "error";
      }else {
       //链接验证通过 转到修改密码页面
       this.getRequest().setAttribute("user", users);
       return "success";
     }
   }else {
     this.getRequest().setAttribute("mesg", "链接错误,无法找到匹配用户,请重新申请找回密码.");
     System.out.println("用户不存在");
     return "error";
   }
 }

public Users getUsers() {
   return users;
 }

public void setUsers(Users users) {
   this.users = users;
 }

public UserHander getUserHander() {
   return userHander;
 }

public void setUserHander(UserHander userHander) {
   this.userHander = userHander;
 }

public String getEmail() {
   return email;
 }

public void setEmail(String email) {
   this.email = email;
 }

public String getSid() {
   return sid;
 }

public void setSid(String sid) {
   this.sid = sid;
 }

public String getUserName() {
   return userName;
 }

public void setUserName(String userName) {
   this.userName = userName;
 }

}

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

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


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

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

源码下载地址:http://pan.baidu.com/s/1cl8hKq

标签:java,密码,邮箱
0
投稿

猜你喜欢

  • spring boot结合Redis实现工具类的方法示例

    2023-05-12 09:47:46
  • IDEA解决src和resource下创建多级目录的操作

    2023-03-24 07:05:37
  • java 安全 ysoserial CommonsCollections6 分析

    2021-06-04 01:58:14
  • 互斥量mutex的简单使用(实例讲解)

    2023-09-20 21:36:50
  • JAVA实现心跳检测(长连接)

    2022-12-16 04:26:30
  • 解决Mybatis映射文件mapper.xml中的注释问题

    2023-09-17 15:06:30
  • 完美实现ExpandableListView二级分栏效果

    2021-07-18 20:04:13
  • Springboot2以代码的方式统一配置Jackson教程

    2021-08-30 16:47:33
  • 设置JavaScript自动提示-Eclipse/MyEclipse

    2022-06-15 12:41:05
  • Java中JUC 的 Exchange 交换器详情

    2023-09-17 18:46:40
  • Java多线程--让主线程等待所有子线程执行完毕在执行

    2022-09-14 01:21:34
  • Java实现上传文件图片到指定服务器目录

    2023-06-28 00:23:32
  • java的各种类型转换全部汇总(推荐)

    2022-03-01 01:25:43
  • Android编程实现使用webView打开本地html文件的方法

    2023-04-26 14:30:38
  • Java封装的实现访问限定符、包

    2023-03-20 07:08:48
  • Android编程基础之获取手机屏幕大小(DisplayMetrics应用)示例

    2023-09-26 17:57:43
  • C#实战之备忘录的制作详解

    2023-08-13 02:17:21
  • c# String扩展 让你在PadLeft和PadRight时不再受单双字节问题困扰

    2022-09-06 12:11:54
  • Spring @Cacheable指定失效时间实例

    2022-12-06 08:58:35
  • SpringBoot中并发定时任务的实现、动态定时任务的实现(看这一篇就够了)推荐

    2023-01-21 13:58:45
  • asp之家 软件编程 m.aspxhome.com