English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

SpringMVC Implementation of Password Recovery Function via Email

I recently developed a system, and there is a requirement to retrieve the password through email after forgetting it. The current system forces the input of email during registration, one of the purposes is to bind the email for password retrieval, and password retrieval can be performed. I won't talk about the function of sending email in Java, the focus is on password retrieval.

Refer to others' ideas: send email → request URL in the email → verify URL → {if verified, change password, if not, jump to the failure page}

The key point is how to generate this URL and how to parse this URL.
It should be noted that a URL can only be modified once, when the same account sends multiple emails, only the URL in the last email

 Encryption can prevent forgery attacks, a URL can only be verified once, and it is bound to the user. Generate URL: Random key can be generated using UUID.

digital signature = MD5(username+’$’+expiration time+‘$'+key)

Database fields (username (primary key), key, expiration time)

URL parameters (username, digital signature), generation of key: A key is generated for each user when the user retrieves the password,

URL example: http://localhost:8080/user/reset_password#63;sid=D622D6A23FBF86FFE696B593D55351A54AEAEA77&userName=test4

Generate expiration time, generate digital signature, generate URL, send email. saveOrUpdate(username, key, expiration time)

The following is springMvc code

@RequestMapping(value = "/user/i_forget_password"
  @ResponseBody
  public Map forgetPass(HttpServletRequest request, String userName){
    Users users = userService.findUserByName(userName);
    Map map = new HashMap<String, String>();
    String msg = "";
    if(users == null){       //Username does not exist
      msg = "Username does not exist, did you forget your username?&63;";
      map.put("msg",msg);
      return map;
    }
    try{
      String secretKey= UUID.randomUUID().toString(); //key
      Timestamp outDate = new Timestamp(System.currentTimeMillis()+30*60*1000);//3expires after 0 minutes
      long date = outDate.getTime()/1000*1000;         //ignore milliseconds
      users.setValidataCode(secretKey);
      users.setRegisterDate(outDate);
      userService.update(users);  //save to database
      String key = users.getUserName()+"$"+date+"$"+secretKey;
      String digitalSignature = MD5.MD5Encode(key);         //Digital Signature
      String emailTitle = "Password Reset for YouFang Cloud";
      String path = request.getContextPath();
      String basePath = request.getScheme()+://"+request.getServerName()+:"+request.getServerPort()+path+"/";
      String resetPassHref = basePath+"user/reset_password#63;sid="+digitalSignature;+"&userName="+users.getUserName();
      String emailContent = "Do not reply to this email. Click the link below to reset your password<br/><a href="+resetPassHref +" target='_BLANK'>Click here to reset your password</a>" +
          "<br/>tips: This email exceeds30 minutes, the link will expire, and you need to apply for 'password reset' again"+key;+"\t"+digitalSignature;
      System.out.print(resetPassHref);
      SendMail.getInstatnce().sendHtmlMail(emailTitle, emailContent, users.getEmail());
      msg = "Operation successful, the password reset link has been sent to your email. Please go to3Reset password within 0 minutes";
      logInfo(request,userName,"Apply to reset password");
    }
      e.printStackTrace();
      msg="Email does not exist? Unknown error, please contact the administrator.";
    }
    map.put("msg",msg);
    return map;
  }

The reset link has been sent to your email. Please open the link in your email

The following is the link verification code, if verified, jump to the password change interface, otherwise jump to the failure interface

@RequestMapping(value = "/user/reset_password", method = RequestMethod.GET)
  public ModelAndView checkResetLink(String sid,String userName){
    ModelAndView model = new ModelAndView("error");
    String msg = "";
    if(sid.equals("") || userName.equals("")){
      msg="Incomplete link, please regenerate.";
      model.addObject("msg",msg) ;
      logInfo(userName,"Password reset link expired");
      return model;
    }
    Users users = userService.findUserByName(userName);
    if(users == null){
      msg = "Link error, cannot find matching user, please reapply to reset your password.";
      model.addObject("msg",msg) ;
      logInfo(userName,"Password reset link expired");
      return model;
    }
    Timestamp outDate = users.getRegisterDate();
    if(outDate.getTime() <= System.currentTimeMillis()){     //Indicates that it has expired
      msg = "The link has expired, please reapply to reset your password.";
      model.addObject("msg",msg) ;
      logInfo(userName,"Password reset link expired");
      return model;
    }
    String key = users.getUserName()+"$"+outDate.getTime()/1000*1000+"$"+users.getValidataCode();     //Digital Signature
    String digitalSignature = MD5.MD5Encode(key);
    System.out.println(key+"\t"+digitalSignature);
    if(!digitalSignature.equals(sid)) {
      msg = "The link is incorrect, has it expired?"63"Reapply";
      model.addObject("msg",msg) ;
      logInfo(userName,"Password reset link expired");
      return model;
    }
    model.setViewName("user/reset_password"); //Return to the change password interface
    model.addObject("userName",userName);
    return model;
  }

Supplementary1:The millisecond accuracy will be lost when the Timestamp type object is saved. For example:2013-10-08 10:29:10.234 When stored in the mysql database, it becomes 2013-10-08 10:29:10.0. The time becomes different, and sid will not be equal when matched. So I did the operation of ignoring accuracy.

Supplementary2:Solve the title Chinese garbled code under Linux

sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
mailMessage.setSubject(MimeUtility.encodeText(mailInfo.getSubject(), "UTF-8", "B");      //Solve the title garbled code of Linux mail

Supplementary3:Why not directly insert sid into the user table? The verification can be done by comparing sid directly.

That's all for this article, I hope it will be helpful to everyone's learning, and I also hope everyone will support the Yelling Tutorial more.

Statement: The content of this article is from the Internet, the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been edited by humans, and does not assume relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email to report abuse, and provide relevant evidence. Once verified, this site will immediately delete the infringing content.)

You May Also Like