Implementation of password recovery function through email
1. Recently, I have developed a system and I have a requirement to retrieve it through my email after forgetting my password. Nowadays, the system will force the email to enter the email address when registering. One of the purposes is to retrieve it through email binding and you can retrieve the password. I won’t talk about the function of sending emails through Java, but focus on retrieving passwords.
2. Refer to other people's ideas: Send email → request URL in email → Verify url → {Verify successfully modify password, but jump to the failed page if it fails}
The point is how to generate this url and how to parse this url.
It should be noted that a url can only modify the password once. When multiple emails are sent by the same account, there is only the url email address of the last email.
3. Encryption can prevent forgery attacks. The URL can only be verified once and binds the user. Generate url: You can use UUID to generate a random key.
Digital signature = MD5 (user name +''+expiration time +''+expiration time +''+key key)
Database field (user name (primary key), key key, expiration time)
url parameters (user name, digital signature), key generation: generate a key key for each user when retrieving the password,
Generate expiration time, generate digital signature, generate url, and send emails. AddU (user name, key, expiration time)
The database used is as follows:
The password to retrieve the email address is as follows:
package com.soq.card.web.action;import java.sql.Timestamp;import java.util.List;import java.util.UUID;import org.hibernate.Criteria;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.criterion.Restrictions;import org.springframework.orm.hibernate3.HibernateTemplate;import com.soq.card.biz.UserHander;import com.soq.card.entity.Users;import com.soq.card.tools.DBhepler;import com.soq.card.tools.Mail;import com.soq.card.tools.Md5;import com.soq.card.web.base.BaseAction;/** * @author javen * @Email [email protected] * */public class PassEmailAction extends BaseAction { private Users users; private UserHander userHander; private String email; private String sid; private String userName; public String sendmail() { try { HibernateTemplate ht = this.getUserHander().getUsersDAO().getHibernateTemplate(); SessionFactory factory = ht.getSessionFactory(); Session session = factory.openSession(); Criteria criteria = session.createCriteria(Users.class); criteria.add(Restrictions.eq("loginName", email)); List<Users> list = criteria.list(); if (list.size() > 0) { users=list.get(0); Mail mail = new Mail(); String secretKey = UUID.randomUUID().toString(); // Key Timestamp outDate = new Timestamp(System.currentTimeMillis() + 30 * 60 * 1000);// Expired after 30 minutes long date = outDate.getTime() / 1000 * 1000;// Ignore the milliseconds mySql The withdrawal time is ignoring the milliseconds DBhepler bhepler=new DBhepler(); String sql="update users set outDate=?,validataCode=? where loginName=?;"; String str[] ={outDate+"",secretKey,users.getLoginName()}; bhepler.AddU(sql, str); //this.getUserHander().getUsersDAO().getHibernateTemplate().update(users); //Save to database System.out.println(" UserName>>>> "+users.getUserName()); String key =users.getUserName() + "$" + date + "$" + secretKey; System.out.println(" key>>>"+key); String digitalSignature = Md5.md5(key);// Digital signature String path = this.getRequest().getContextPath(); String basePath = this.getRequest().getScheme() + "://" + this.getRequest().getServerName() + ":" + this.getRequest().getServerPort() + path + "/"; String resetPassHref = basePath + "checkLink?sid=" + digitalSignature +"&userName="+users.getUserName(); String emailContent = "Do not reply to this email. Click the link below to reset your password<br/><a href=" + resetPassHref + " target='_BLANK'>" + resetPassHref + "</a> Or <a href=" + resetPassHref + " target='_BLANK'>Click me to reset your password</a>" + "<br/>tips: This email will expire after more than 30 minutes. You need to re-apply for 'retrieval password'" + key + "/t" + digitalSignature; mail.setTo(email); mail.setFrom("XX");// Your email address mail.setHost("smtp.163.com"); mail.setUsername("[email protected]");// User mail.setPassword("CXXX");// Password mail.setSubject("[QR code business card] Retrieve your account password"); mail.setContent(emailContent); if (mail.sendMail()) { System.out.println("SendSuccessfully Send"); this.getRequest().setAttribute("mesg", "Reset password The email has been sent, please log in to the email address to reset it! "); return "sendMail"; } } else { this.getRequest().setAttribute("mesg", "The username does not exist, you will not forget your mailbox, right?"); return "noUser"; } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return null; } public String checkResetLink() { System.out.println("sid>>>" + sid); if (sid.equals("") || userName.equals("")) { this.getRequest().setAttribute("mesg", "The link is incomplete, please regenerate"); System.out.println(">>>>> null"); return "error"; } HibernateTemplate ht = this.getUserHander().getUsersDAO().getHibernateTemplate(); SessionFactory factory = ht.getSessionFactory(); Session session = factory.openSession(); Criteria criteria = session.createCriteria(Users.class); criteria.add(Restrictions.eq("userName", userName)); List<Users> list = criteria.list(); if (list.size()>0) { users=list.get(0); Timestamp outDate = (Timestamp) users.getOutDate(); System.out.println("outDate>>>"+outDate); if(outDate.getTime() <= System.currentTimeMillis()){ // means that this.getRequest().setAttribute("mesg", "The link has expired, please reapply to retrieve the password."); System.out.println("Time Timeout"); return "error"; } String key = users.getUserName()+"$"+outDate.getTime()/1000*1000+"$"+users.getValidataCode();//Digital signature System.out.println("key link》"+key); String digitalSignature = Md5.md5(key);//Digital signature System.out.println("digitalSignature>>>>"+digitalSignature); if(!digitalSignature.equals(sid)) { this.getRequest().setAttribute("mesg", "The link is incorrect, has it expired? Re-apply."); System.out.println("incorrect label"); return "error"; }else { //The link verification is by going to the password modification page this.getRequest().setAttribute("user", users); return "success"; } }else { this.getRequest().setAttribute("mesg", "The link is incorrect, the matching user cannot be found, please re-apply to retrieve the password."); System.out.println("User does not exist"); return "error"; } } public Users getUsers() { return users; } public void setUsers(Users users) { this.users = users; } public UserHander getUserHander() { return userHander; } public void setUserHander(UserHander userHander) { this.userHander = userHander; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; }}
Supplement 1: Millisecond accuracy will be lost when saving to data. For example: 2014-05-20 10:30:10.234 When stored in the mysql database, it becomes 2013-05-20 10:30:10.0. Times become different, and sid matches will not be equal. So I did an operation that ignored the accuracy.
Supplement 2: Solve Chinese garbled code in titles below linux
sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();mailMessage.setSubject(MimeUtility.encodeText(mailInfo.getSubject(), "UTF-8", "B")); //Solve linux mail title garbled
Supplement 3: Why don’t you insert sid into the users table directly? It would be OK to directly compare sid when verifying.
Source code download address: http://pan.baidu.com/s/1cl8hKq
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.