1, recently developed a system, there is a need to forget the password after the mailbox back. Now the system at the time of registration will be forced to enter the mailbox, its purpose is to get back through the mail binding, can be password back. The ability to send mail through Java I will not say, focus on retrieving the password.
2, refer to other people's ideas: Send mail → url→ verification in the request email url→{authentication successfully changed password, unsuccessful jump to failure page}
The point is how to generate this URL and how to parse it.
Note that a URL can only be modified once password, when the same account to send multiple messages, only the last message URL
3, encryption can prevent forgery attacks, one URL can only be verified once, and bind the user. Generate URL: The random key can be generated with the UUID.
Digital signature = MD5 (username + ' $ ' + expiry time + ' $ ' + key key)
Database fields (user name (primary key), key key, expiration time)
URL parameters (user name, digital signature), the generation of key key: Generate a key key for this user when each user retrieves the password
URL Example:http://localhost:8080/user/reset_password?sid=d622d6a23fbf86ffe696b593d55351a54aeaea77&username =test4
Generates an expiration time, generates a digital signature, generates a URL, and sends a message. Saveorupdate (username, key, expiry time)
The following is the SPRINGMVC code
1@RequestMapping (value = "/user/i_forget_password")2 @ResponseBody3 PublicMap forgetpass (httpservletrequest request,string userName) {4Users users =Userservice.finduserbyname (userName);5Map map =NewHashmap<string, String >();6String msg = "";7 if(Users = =NULL){//user name does not exist8msg = "User name does not exist, you will not forget the user name, right?";9Map.put ("MSG", msg);Ten returnmap; One } A Try{ -String secretkey= Uuid.randomuuid (). toString ();//secret key -Timestamp outdate =NewTimestamp (System.currenttimemillis () +30*60*1000);//expires after 30 minutes the LongDate = Outdate.gettime ()/1000*1000;//ignore the number of milliseconds - Users.setvalidatacode (secretkey); - users.setregisterdate (outdate); -Userservice.update (users);//Save to database +String key = Users.getusername () + "$" +date+ "$" +Secretkey; -String digitalsignature = MD5. Md5encode (key);//Digital Signatures + AString emailtitle = "Party Cloud password Retrieved"; atString 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 = "Do not reply to this message. Click on the link below, reset the password <br/><a href=" +resetpasshref + "target= ' _blank ' > click I reset Password < /a> "+ -"<br/>tips: This message is more than 30 minutes, the link will be invalid, need to re-apply ' recover password '" +key+ "\ T" +digitalsignature; - System.out.print (resetpasshref); in sendmail.getinstatnce (). Sendhtmlmail (Emailtitle,emailcontent,users.getemail ()); -msg = "The operation was successful, the password has been sent back to your mailbox." Please reset your password within 30 minutes "; toLoginfo (Request,username, "Apply to retrieve password"); +}Catch(Exception e) { - e.printstacktrace (); themsg= "Mailbox does not exist? Unknown error, contact the administrator. "; * } $Map.put ("MSG", msg);Panax Notoginseng returnmap; -}
The back link has been sent to the mailbox. Go to the mailbox point open link
The following is the link inspection Code, verification by jumping to modify the password interface, otherwise jump to the failed interface
1@RequestMapping (value = "/user/reset_password", method =requestmethod.get)2 PublicModelandview checkresetlink (String sid,string userName) {3Modelandview model =NewModelandview ("Error");4String msg = "";5 if(Sid.equals ("") | | Username.equals ("")){6Msg= "The link is incomplete, please regenerate";7Model.addobject ("MSG", msg);8Loginfo (userName, "Retrieve Password link Invalid");9 returnmodel;Ten } OneUsers users =Userservice.finduserbyname (userName); A if(Users = =NULL){ -msg = "Link error, unable to find a matching user, please re-request password recovery."; -Model.addobject ("MSG", msg); theLoginfo (userName, "Retrieve Password link Invalid"); - returnmodel; - } -Timestamp outdate =users.getregisterdate (); + if(Outdate.gettime () <= System.currenttimemillis ()) {//indicates that it has expired -msg = "The link has expired, please re-apply to retrieve the password."; +Model.addobject ("MSG", msg); ALoginfo (userName, "Retrieve Password link Invalid"); at returnmodel; - } -String key = Users.getusername () + "$" +outdate.gettime ()/1000*1000+ "$" +users.getvalidatacode ();//Digital Signatures -String digitalsignature =MD5. Md5encode (key); -System.out.println (key+ "\ T" +digitalsignature); - if(!digitalsignature.equals (SID)) { inmsg = "link is not correct, has expired?" re-apply.; -Model.addobject ("MSG", msg); toLoginfo (userName, "Retrieve Password link Invalid"); + returnmodel; - } theModel.setviewname ("User/reset_password");//return to the interface to modify the password *Model.addobject ("UserName", userName); $ returnmodel;Panax Notoginseng}
Supplemental 1:timestamp Type objects are lost in milliseconds when they are saved to the data. For example: 2013-10-08 10:29:10.234 into the MySQL database when the 2013-10-08 10:29:10.0. Time becomes different, and Sid matches are not equal. So I did the operation of ignoring the precision.
Supplement 2: Fix Linux under title Chinese garbled
1 New Sun.misc.BASE64Encoder (); 2 Mailmessage.setsubject (Mimeutility.encodetext (Mailinfo.getsubject (), "UTF-8", "B")); // troubleshoot Linux message title garbled
Add 3: Why not directly insert the SID into the user table? The direct comparison of SIDS is OK when validating.
SPRINGMVC the ability to retrieve passwords via mail