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

Implementação da função de recuperação de senha por e-mail no SpringMVC

Recentemente, desenvolvi um sistema, que tinha uma necessidade de, após esquecer a senha, recuperar por e-mail. O sistema atual força a entrada de e-mail no momento do registro, um dos objetivos é através do e-mail para restaurar, permitindo que você recupere a senha. Eu não vou falar sobre a função de envio de e-mail em java, o ponto principal é recuperar a senha.

Referência de pensamento de outros: enviar e-mail → URL no e-mail solicitado → verificar url → {se verificar com sucesso, modificar a senha, se não, redirecionar para a página de falha}

O ponto principal é como gerar essa url e como analisar essa url.
Deve-se notar que uma url pode ser modificada apenas uma vez, quando o mesmo nome de usuário enviar vários e-mails, apenas a url do último e-mail

 criptografia pode evitar ataques de falsificação, uma url pode ser verificada apenas uma vez e está vinculada ao usuário. Geração de url: pode usar UUID para gerar uma chave secreta aleatória.

assinatura digital = MD5(nome de usuário+'$'+tempo de expiração+‘$'+chave secreta)

campos do banco de dados (nome de usuário (chave primária), chave secreta, tempo de expiração)

url parâmetros (nome de usuário, assinatura digital) , geração de chave secreta: a cada vez que um usuário recuperar a senha, gerar uma chave secreta para esse usuário ,

url exemplo: http://localhost:8080/user/reset_password#63;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) {       //O nome de usuário não existe
      msg = "O nome de usuário não existe, você não se lembra do nome de usuário?&"63;";
      map.put("msg", msg);
      return map;
    }
    try{
      String secretKey= UUID.randomUUID().toString(); //chave
      Timestamp outDate = new Timestamp(System.currentTimeMillis()+30*60*1000);//3expira após 0 minutos
      long date = outDate.getTime()/1000*1000;         //ignorar a casa decimal
      users.setValidataCode(secretKey);
      users.setRegisterDate(outDate);
      userService.update(users);  //salvar no banco de dados
      String key = users.getUserName()+"$"+date+"$"+secretKey;
      String digitalSignature = MD5.MD5Encode(key);         //Assinatura Digital
      String emailTitle = "Recuperação de senha da Cloud YouField";
      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 = "Não responda a este e-mail. Clique no link abaixo para redefinir sua senha<br/><a href="+resetPassHref; +" target='_BLANK'>Clique aqui para redefinir sua senha</a>" +
          "<br/>dicas: Este e-mail expira após30 minutos, o link expirará e será necessário solicitar novamente a 'redefinição de senha'."+key;+"\t"+digitalSignature;
      System.out.print(resetPassHref);
      SendMail.getInstatnce().sendHtmlMail(emailTitle, emailContent, users.getEmail());
      msg = "Operação bem-sucedida, já foi enviado um link para redefinição de senha para o seu e-mail. Por favor,\n"3Redefinir senha dentro de 0 minutos";
      logInfo(request, userName, "Solicitação de recuperação de senha");
    }
      e.printStackTrace();
      msg = "E-mail não existe? Erro desconhecido, entre em contato com o administrador.";
    }
    map.put("msg", msg);
    return map;
  }

O link de recuperação foi enviado para o e-mail. Abra o e-mail e clique no link

O código de verificação do link a seguir, se for verificado com sucesso, será redirecionado para a página de alteração de senha, caso contrário, será redirecionado para a página de falha

@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, por favor, gere novamente.";
      model.addObject("msg",msg) ;
      logInfo(userName,"Link de recuperação de senha expirado");
      return model;
    }
    Users users = userService.findUserByName(userName);
    if (users == null) {
      msg = "Link incorreto, usuário não encontrado, por favor, faça o pedido de recuperação de senha novamente.";
      model.addObject("msg",msg) ;
      logInfo(userName,"Link de recuperação de senha expirado");
      return model;
    }
    Timestamp outDate = users.getRegisterDate();
    if (outDate.getTime() <= System.currentTimeMillis()) {     //Indica que expirou
      msg = "O link expirou, por favor, faça o pedido de recuperação de senha novamente.";
      model.addObject("msg",msg) ;
      logInfo(userName,"Link de recuperação de senha expirado");
      return model;
    }
    String key = users.getUserName()+"$"+outDate.getTime()/1000*1000+"$"+users.getValidataCode();     //Assinatura Digital
    String digitalSignature = MD5.MD5Encode(key);
    System.out.println(key+"\t"+digitalSignature);
    if (!digitalSignature.equals(sid)) {
      msg = "O link está incorreto, já expirou?"63;Refaça o pedido ";
      model.addObject("msg",msg) ;
      logInfo(userName,"Link de recuperação de senha expirado");
      return model;
    }
    model.setViewName("user/reset_password"); //Voltar para a interface de alterar senha
    model.addObject("userName",userName);
    return model;
  }

Suplemento1:O objeto Timestamp perde a precisão de milissegundos ao ser salvo. Por exemplo:2013-10-08 10:29:10.234 Quando é armazenado no banco de dados mysql se torna 2013-10-08 10:29:10.0. O tempo se torna diferente, quando sid coincide não será igual. Portanto, fiz a operação de ignorar a precisão.

Suplemento2:Solucionar a codificação de caractere errada do título do e-mail no Linux

sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
mailMessage.setSubject(MimeUtility.encodeText(mailInfo.getSubject(), "UTF-8", "B");      //Solucionar a codificação de caractere errada do título do e-mail no Linux

Suplemento3:Por que não inserir diretamente sid na tabela user? A verificação pode ser feita diretamente comparando sid.

Isso é tudo o que há no artigo, espero que ajude no seu aprendizado e que você apóie o tutorial Gargalhadas.

Declaração: O conteúdo deste artigo é proveniente da Internet, pertence ao autor original, foi contribuído e carregado voluntariamente pelos usuários da Internet, o site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidades legais relacionadas. Se você encontrar conteúdo suspeito de infringir direitos autorais, por favor, envie e-mail para: notice#oldtoolbag.com (ao enviar e-mail, substitua # por @ para denunciar e forneça provas relevantes. Em caso de verificação, o site deletará imediatamente o conteúdo suspeito de infringir direitos autorais.)

Você também pode gostar