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

Implementazione della funzione di recupero della password tramite email in SpringMVC

Di recente, sviluppando un sistema, c'era la necessità di reimpostare la password tramite l'email. Il sistema attuale costringe l'utente a inserire un'email durante la registrazione, uno dei motivi è per bindare tramite email e permettere il recupero della password. Non parlo della funzione di invio email in Java, ma concentrandomi sul recupero della password.

Reference others' ideas: send email → request URL in the email → verify URL → {If verified successfully, change the 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 used to change the password once, when the same account sends multiple emails, only the url of the last email

 Encryption can prevent forgery attacks, a url can only be verified once, and it is bound to the user. Generate url: You can use UUID to generate a random key.

Digital signature = MD5(username+'$'+expiration time+'$'+key key)

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

url parameters (username, digital signature), the generation of key key: For each user who retrieves the password, a key key is generated for this user,

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

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

The following is the 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, won't you forget the username?";
      map.put("msg",msg);
      return map;
    }
    try{
      String secretKey= UUID.randomUUID().toString(); //Key
      Timestamp outDate = new Timestamp(System.currentTimeMillis()+30*60*1000);//Expires 30 minutes later
      long date = outDate.getTime()/1000*1000;         //Neglect the millisecond number
      users.setValidataCode(secretKey);
      users.setRegisterDate(outDate);
      userService.update(users);  //salvare nel database
      String key = users.getUserName()+"$"+date+"$"+secretKey;
      String digitalSignature = MD5.MD5Encode(key);         //firma digitale
      String emailTitle = "Recupero password di Youfang Cloud";
      String path = request.getContextPath();
      String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
      String resetPassHref = basePath+"user/reset_password?sid="+digitalSignature+"&userName="+users.getUserName();
      String emailContent = "Non rispondere a questa email. Clicca sul link sottostante per reimpostare la password<br/><a href="+resetPassHref +" target='_BLANK'>Clicca qui per reimpostare la password</a>" +
          "<br/>avviso: questa email è scaduta dopo 30 minuti, il link non è più valido, è necessario richiedere di nuovo 'recupero della password'"+key+"\t"+digitalSignature;
      System.out.print(resetPassHref);
      SendMail.getInstatnce().sendHtmlMail(emailTitle,emailContent,users.getEmail());
      msg = "操作成功,已经发送找回密码链接到您邮箱。请在30分钟内重置密码";
      logInfo(request,userName,"申请找回密码");
    }catch (Exception e){
      e.printStackTrace();
      msg="邮箱不存在?未知错误,联系管理员吧。";
    }
    map.put("msg",msg);
    return map;
  }

Il link di recupero è stato inviato all'email. Apri l'email e fai clic sul link

Il seguente è il codice di verifica del link, se superato il controllo, viene reindirizzato alla schermata di modifica della password, altrimenti alla schermata di fallimento

@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="Link incompleto, generalo di nuovo";
      model.addObject("msg",msg) ;
      logInfo(userName,"link di recupero della password non valido");
      return model;
    }
    Users users = userService.findUserByName(userName);
    if(users == null){
      msg = "Link errato, non è possibile trovare l'utente corrispondente, richiedi di nuovo per recuperare la password.";
      model.addObject("msg",msg) ;
      logInfo(userName,"link di recupero della password non valido");
      return model;
    }
    Timestamp outDate = users.getRegisterDate();
    if(outDate.getTime() <= System.currentTimeMillis()){     // indica che è scaduto
      msg = "Il link è scaduto, richiedi di nuovo per recuperare la password.";
      model.addObject("msg",msg) ;
      logInfo(userName,"link di recupero della password non valido");
      return model;
    }
    String key = users.getUserName()+"$"+outDate.getTime()/1000*1000+"$"+users.getValidataCode();     // firma digitale
    String digitalSignature = MD5.MD5Encode(key);
    System.out.println(key+"\t"+digitalSignature);
    if(!digitalSignature.equals(sid)) {
      msg = "Il link non è corretto, è scaduto? Richiedi di nuovo";
      model.addObject("msg",msg) ;
      logInfo(userName,"link di recupero della password non valido");
      return model;
    }
    model.setViewName("user/reset_password"); // tornare alla schermata di modifica della password
    model.addObject("userName",userName);
    return model;
  }

Aggiunta 1:Quando un oggetto di tipo Timestamp viene salvato nei dati, l'accuratezza dei millisecondi viene persa. Ad esempio: 2013-10-08 10:29:10.234 quando salvato nel database MySQL diventa 2013-10-08 10:29:10.0. L'ora diventa diversa, quindi quando si confronta sid non saranno uguali. Quindi ho eseguito l'operazione di ignoranza dell'accuratezza.

Aggiunta 2:Risolve il problema di encoding errato del titolo delle email in cinese su Linux

sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
mailMessage.setSubject(MimeUtility.encodeText(mailInfo.getSubject(), "UTF-8", "B")); // Risolve il problema di encoding errato del titolo delle email su Linux

Aggiunta 3:Perché non inserire direttamente sid nella tabella user. Durante la verifica, confronta direttamente sid e sarà sufficiente.

Questo è tutto il contenuto dell'articolo, speriamo che sia utile per la tua apprendimento, e speriamo che tutti possano sostenere e applaudire i tutorial.

Dichiarazione: il contenuto di questo articolo è stato prelevato da Internet, di proprietà del rispettivo autore, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non detiene i diritti di proprietà, non è stato editato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una e-mail a: notice#oldtoolbag.com (al momento dell'invio dell'e-mail, sostituisci # con @) per segnalare, fornendo prove pertinenti. Una volta verificata, questo sito rimuoverà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare