Java實(shí)現(xiàn)郵箱找回密碼實(shí)例代碼
通過(guò)郵件找回密碼功能的實(shí)現(xiàn)
1、最近開發(fā)一個(gè)系統(tǒng),有個(gè)需求就是,忘記密碼后通過(guò)郵箱找回?,F(xiàn)在的系統(tǒng)在注冊(cè)的時(shí)候都會(huì)強(qiáng)制輸入郵箱,其一目的就是 通過(guò)郵件綁定找回,可以進(jìn)行密碼找回。通過(guò)java發(fā)送郵件的功能我就不說(shuō)了,重點(diǎn)講找回密碼。
2、參考別人的思路:發(fā)送郵件→請(qǐng)求郵件里的URL→驗(yàn)證url→{驗(yàn)證成功修改密碼,不成功跳轉(zhuǎn)到失敗頁(yè)面}
重點(diǎn)就是如何生成這個(gè)url和如何解析這個(gè)url.
需要注意的是一個(gè)url只能修改一次密碼,當(dāng)同一帳號(hào)發(fā)送多封郵件,只有最后一封郵件的url 郵箱
3、加密能防止偽造攻擊,一次url只能驗(yàn)證一次,并且綁定了用戶。生成url: 可以用UUID生成隨機(jī)密鑰。
數(shù)字簽名 = MD5(用戶名+'′+過(guò)期時(shí)間+‘′+過(guò)期時(shí)間+‘'+密鑰key)
數(shù)據(jù)庫(kù)字段(用戶名(主鍵),密鑰key,過(guò)期時(shí)間)
url參數(shù)(用戶名,數(shù)字簽名) ,密鑰key的生成:在每一個(gè)用戶找回密碼時(shí)候?yàn)檫@個(gè)用戶生成一個(gè)密鑰key ,
生成過(guò)期時(shí)間,生成數(shù)字簽名,生成url,發(fā)送郵件. AddU(用戶名,密鑰key,過(guò)期時(shí)間)
使用到的數(shù)據(jù)庫(kù)如下 :
找回郵箱密碼代碼如下:
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 zyw205@gmail.com
*
*/
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(); // 密鑰
Timestamp outDate = new Timestamp(System.currentTimeMillis() + 30 * 60 * 1000);// 30分鐘后過(guò)期
long date = outDate.getTime() / 1000 * 1000;// 忽略毫秒數(shù) mySql 取出時(shí)間是忽略毫秒數(shù)的
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); // 保存到數(shù)據(jù)庫(kù)
System.out.println(" UserName>>>> "+users.getUserName());
String key =users.getUserName() + "$" + date + "$" + secretKey;
System.out.println(" key>>>"+key);
String digitalSignature = Md5.md5(key);// 數(shù)字簽名
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 = "請(qǐng)勿回復(fù)本郵件.點(diǎn)擊下面的鏈接,重設(shè)密碼<br/><a href="
+ resetPassHref + " target='_BLANK'>" + resetPassHref
+ "</a> 或者 <a href=" + resetPassHref
+ " target='_BLANK'>點(diǎn)擊我重新設(shè)置密碼</a>"
+ "<br/>tips:本郵件超過(guò)30分鐘,鏈接將會(huì)失效,需要重新申請(qǐng)'找回密碼'" + key
+ "\t" + digitalSignature;
mail.setTo(email);
mail.setFrom("XX");// 你的郵箱
mail.setHost("smtp.163.com");
mail.setUsername("XXX@163.com");// 用戶
mail.setPassword("CXXX");// 密碼
mail.setSubject("[二維碼名片]找回您的賬戶密碼");
mail.setContent(emailContent);
if (mail.sendMail()) {
System.out.println(" 發(fā)送成功");
this.getRequest().setAttribute("mesg", "重置密碼郵件已經(jīng)發(fā)送,請(qǐng)登陸郵箱進(jìn)行重置!");
return "sendMail";
}
} else {
this.getRequest().setAttribute("mesg", "用戶名不存在,你不會(huì)忘記郵箱了吧?");
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", "鏈接不完整,請(qǐng)重新生成");
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()){ //表示已經(jīng)過(guò)期
this.getRequest().setAttribute("mesg", "鏈接已經(jīng)過(guò)期,請(qǐng)重新申請(qǐng)找回密碼.");
System.out.println("時(shí)間 超時(shí)");
return "error";
}
String key = users.getUserName()+"$"+outDate.getTime()/1000*1000+"$"+users.getValidataCode();//數(shù)字簽名
System.out.println("key link》》"+key);
String digitalSignature = Md5.md5(key);// 數(shù)字簽名
System.out.println("digitalSignature>>>>"+digitalSignature);
if(!digitalSignature.equals(sid)) {
this.getRequest().setAttribute("mesg", "鏈接不正確,是否已經(jīng)過(guò)期了?重新申請(qǐng)吧.");
System.out.println("標(biāo)示不正確");
return "error";
}else {
//鏈接驗(yàn)證通過(guò) 轉(zhuǎn)到修改密碼頁(yè)面
this.getRequest().setAttribute("user", users);
return "success";
}
}else {
this.getRequest().setAttribute("mesg", "鏈接錯(cuò)誤,無(wú)法找到匹配用戶,請(qǐng)重新申請(qǐng)找回密碼.");
System.out.println("用戶不存在");
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;
}
}
補(bǔ)充1:Timestamp類型對(duì)象在保存到數(shù)據(jù)的時(shí)候 毫秒精度會(huì)丟失。比如:2014-05-20 10:30:10.234 存到mysql數(shù)據(jù)庫(kù)的時(shí)候 變成 2013-05-20 10:30:10.0。時(shí)間變得不相同了,sid 匹配的時(shí)候不會(huì)相等。 所以我做了忽略精度的操作。
補(bǔ)充2:解決linux下面title中文亂碼
sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder(); mailMessage.setSubject(MimeUtility.encodeText(mailInfo.getSubject(), "UTF-8", "B")); //解決linux郵件title亂碼
補(bǔ)充3:怎么不直接把sid插入到users表呢。驗(yàn)證的時(shí)候直接比較sid就ok了。
源碼下載地址:http://pan.baidu.com/s/1cl8hKq
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于Java SSM的健康管理小程序的實(shí)現(xiàn)
本篇文章主要為大家分享了基于SSM健康管理小程序的設(shè)計(jì)與實(shí)現(xiàn)。感興趣的小伙伴可以了解一下2021-11-11
談?wù)凷pring Boot 數(shù)據(jù)源加載及其多數(shù)據(jù)源簡(jiǎn)單實(shí)現(xiàn)(小結(jié))
這篇文章主要介紹了談?wù)凷pring Boot 數(shù)據(jù)源加載及其多數(shù)據(jù)源簡(jiǎn)單實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-04-04
Java讀取properties文件內(nèi)容的幾種方式詳解
這篇文章主要介紹了Java讀取properties文件內(nèi)容的幾種方式詳解,讀取properties配置文件在實(shí)際的開發(fā)中使用的很多,本文來(lái)介紹常用的幾種實(shí)現(xiàn)方式,需要的朋友可以參考下2023-11-11
springboot集成mybatisPlus+多數(shù)據(jù)源的實(shí)現(xiàn)示例
這篇文章主要介紹了springboot集成mybatisPlus+多數(shù)據(jù)源的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
SpringMvc接受請(qǐng)求參數(shù)的幾種情況演示
Springmvc接受請(qǐng)求參數(shù)的幾種介紹,如何接受json請(qǐng)求參數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-07-07
Java對(duì)象以Hash結(jié)構(gòu)存入Redis詳解
這篇文章主要介紹了Java對(duì)象以Hash結(jié)構(gòu)存入Redis詳解,和Java中的對(duì)象非常相似,卻不能按照J(rèn)ava對(duì)象的結(jié)構(gòu)直接存儲(chǔ)進(jìn)Redis的hash中,因?yàn)镴ava對(duì)象中的field是可以嵌套的,而Redis的Hash結(jié)構(gòu)不支持嵌套結(jié)構(gòu),需要的朋友可以參考下2023-08-08
Java經(jīng)典快排思想以及快排的改進(jìn)講解
今天小編就為大家分享一篇關(guān)于Java經(jīng)典快排思想以及快排的改進(jìn)講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01

