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