继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Java实现邮箱找回密码

大叔_fighting
关注TA
已关注
手记 81
粉丝 44
获赞 400

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

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

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

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

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

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

url example:http://www.wechat68.com:80/CardSSHOK/checkLink?sid=K3xHOi4o/UihH5QYWBDfYA==&userName=123

生成过期时间,生成数字签名,生成url,发送邮件. AddU(用户名,密钥key,过期时间)
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中文乱码

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

打开App,阅读手记
4人推荐
发表评论
随时随地看视频慕课网APP

热门评论

可以只给邮箱发送验证码,并存到redis中

查看全部评论