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