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

Implementation de la fonction de récupération du mot de passe par e-mail dans SpringMVC

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

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

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

 加密能防止伪造攻击,一次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代码

@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){       //Le nom d'utilisateur n'existe pas
      msg = "Le nom d'utilisateur n'existe pas, vous ne vous souvenez pas de votre nom d'utilisateur ?&63;";
      map.put("msg",msg);
      return map;
    }
    try{
      String secretKey= UUID.randomUUID().toString(); //clé
      Timestamp outDate = new Timestamp(System.currentTimeMillis()+30*60*1000);//3expire après 0 minutes
      long date = outDate.getTime()/1000*1000;         //ignorer les millisecondes
      users.setValidataCode(secretKey);
      users.setRegisterDate(outDate);
      userService.update(users);  //enregistrer dans la base de données
      String key = users.getUserName()+"$"+date+"$"+cléSecrète;
      String digitalSignature = MD5.MD5Encode(key);         //Signature numérique
      String emailTitle = "Récupération de mot de passe Cloud You";
      String path = request.getContextPath();
      String basePath = request.getScheme()+":"//"+request.getServerName()+":"+request.getServerPort()+chemin+"/";
      String resetPassHref = basePath+"user/reset_password?sid="+signatureDigitale+"&userName="+users.getUserName();
      String emailContent = "Ne répondez pas à cet e-mail. Cliquez sur le lien suivant pour réinitialiser votre mot de passe<br/><a href="+resetPassHref +" cible='_BLANK'>Cliquez ici pour réinitialiser votre mot de passe</a>" +
          "<br/>astuce : cet e-mail est valide pendant30 minute, le lien expirera et vous devrez demander à nouveau la récupération de mot de passe"+clé+"\t"+signatureDigitale;
      System.out.print(resetPassHref);
      SendMail.getInstatnce().sendHtmlMail(emailTitle, emailContent, users.getEmail());
      msg = "Opération réussie, un lien de récupération de mot de passe a été envoyé à votre adresse e-mail. Veuillez aller à3Changement de mot de passe dans les 0 minutes";
      logInfo(request,userName,"Demande de récupération du mot de passe");
    }catch (Exception e){
      e.printStackTrace();
      msg="Adresse e-mail inexistante ? Erreur inconnue, contactez l'administrateur.";
    }
    map.put("msg",msg);
    return map;
  }

Le lien de récupération a été envoyé par e-mail. Ouvrez l'e-mail et cliquez sur le lien

Le code de vérification du lien suivant, si validé, redirige vers l'interface de modification du mot de passe, sinon redirige vers l'interface d'échec

@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="Lien incomplet, veuillez le regénérer";
      model.addObject("msg",msg) ;
      logInfo(userName,"Le lien de récupération du mot de passe a expiré");
      return model;
    }
    Users users = userService.findUserByName(userName);
    if(users == null){
      msg = "Lien incorrect, utilisateur introuvable, veuillez réessayer de demander à récupérer le mot de passe.";
      model.addObject("msg",msg) ;
      logInfo(userName,"Le lien de récupération du mot de passe a expiré");
      return model;
    }
    Timestamp outDate = users.getRegisterDate();
    if(outDate.getTime() <= System.currentTimeMillis()){     //Indique que cela a expiré
      msg = "Lien expiré, veuillez réessayer de demander à récupérer le mot de passe.";
      model.addObject("msg",msg) ;
      logInfo(userName,"Le lien de récupération du mot de passe a expiré");
      return model;
    }
    String key = users.getUserName()+"$"+outDate.getTime()/1000*1000+"$"+users.getValidataCode();     //Signature numérique
    String digitalSignature = MD5.MD5Encode(key);
    System.out.println(key+"\t"+digitalSignature);
    if(!digitalSignature.equals(sid)) {
      msg = "Lien incorrect, a-t-il expiré?"63";Réessayer la demande";
      model.addObject("msg",msg) ;
      logInfo(userName,"Le lien de récupération du mot de passe a expiré");
      return model;
    }
    model.setViewName("user/reset_password"); //Retour à l'interface de modification du mot de passe
    model.addObject("userName",userName);
    return model;
  }

Complément1:Les objets de type Timestamp perdent leur précision en millisecondes lors de leur enregistrement. Par exemple :2013-10-08 10:29:10.234 Enregistré dans la base de données mysql, il devient 2013-10-08 10:29:10.0. Le temps est devenu différent, sid ne correspond pas lorsque sid correspond.

Complément2:Résoudre le problème de codage des caractères chinois dans le titre sous Linux

sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
mailMessage.setSubject(MimeUtility.encodeText(mailInfo.getSubject(), "UTF-8"B");      //Résoudre le problème de codage des caractères chinois dans le titre du courrier électronique sous Linux

Complément3:Pourquoi ne pas insérer directement sid dans la table user ? La vérification se fait directement en comparant sid, cela suffit.

Voici la totalité du contenu de cet article, j'espère qu'il vous sera utile dans vos études, et j'espère que vous soutiendrez également le tutoriel criant.

Déclaration : le contenu de cet article est issu du réseau, la propriété intellectuelle appartient à ses auteurs respectifs, le contenu est contribué et téléversé par les utilisateurs d'Internet, ce site ne détient pas de droits de propriété, n'a pas été traité par l'éditeur humain et n'assume aucune responsabilité juridique connexe. Si vous trouvez du contenu suspect de violation de droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, ce site supprimera immédiatement le contenu suspect de violation de droits d'auteur.)

Vous pourriez aussi aimer