前言
本文将介紹忘記密碼時通過發送重置密碼郵件找回密碼的實作思路。整個實作過程中最重要的就是以下三點:
- 如何發送郵件到使用者指定郵箱
- 郵件中的重置密碼連結構成是怎麼樣的
- 驗證重置密碼連結的合法性(是否過期)
先來個實作的效果展示吧,然後再仔細分析如何去實作各個部分:
效果展示
(這裡盜用下我們小組作品成果的前端)
使用者輸入注冊時的郵箱賬戶擷取重置密碼的連結
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuATM2cTN1QDM30SM2ADNzMzM5ETMyYDM5EDMy0SOxQTO5ATMvwlNwkTMwIzLclTM0kTOwEzLcd2bsJ2Lc12bj5ycn9Gbi52YugTMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
使用者登入自己的郵箱檢視郵件
使用者點選重置密碼連結,如果在重置連結有效期内我們跳轉到重置密碼界面,否則提醒使用者該連結已過期
如何發送郵件給使用者指定的郵箱
在整體看了效果之後,我們就來逐漸分析功能實作。首先是發郵件,這個功能我借用了一位部落客寫好的代碼,這雖然是他09年寫的,但是實作效果依舊很好。代碼中的注釋也很詳細,我也不用再多做解釋(實際情況是,我也沒有太認真去讀該代碼,隻是當了一個搬運工,哈哈~)。文末附上了該部落客的部落格連結。我發送郵件的demo可見github:
然後介紹下在使用過程遇見的坑,不出意外十有八九大家都會遇見。主要有兩個:
認證錯誤:javax.mail.AuthenticationFailedException
也就是報錯如下:
這也是因為,在填寫發送郵件的密碼時,應該使用授權碼,而不是密碼!!!
郵件内容不合法:com.sun.mail.smtp.SMTPSendFailedException: 554
這個是因為你的郵件被網易郵箱(我用的是網易郵箱發郵件)識别成垃圾郵件,然後就不會給你發。我的解決辦法是,修改郵件的内容,僅包含少量的提示資訊和重置密碼連結。這樣就成功地發送了。
如何發送郵件這個問題解決,那麼下一步就是,郵件中的重置密碼連結應該是怎樣?
包導入出錯
Constructor PasswordAuthentication can not be applied to given types.
required java.lang.String,java.lang.char[]
出現這個問題的原因是我們導錯了包
不應該為
import java.net.Authenticator;
import java.net.PasswordAuthentication;
而要導入
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
重置密碼連結的生成
重置密碼連結中應該最少包含兩個資訊:
使用者的辨別
和
連結的有效時間
。使用者辨別是為了指定為哪個重置密碼,而有效時間是從安全性角度來看是為了重播攻擊。我這次就實作就在連結中僅包含了這兩個資訊,如果有需求可以加入更多辨別資訊。
然後最重要的一點就是,要對資訊加密!!如果不加密的話就很容易遭受篡改攻擊!還需要注意,我們不能使用hash算法加密,如md5。從本質上講md5不算是加密算法,是一種單向的産生散列值的算法,用于檢驗資訊的完整性。加密算法要求可以解密,是可逆的。
在本次demo中,我使用了DES算法對使用者辨別(使用者輸入的郵箱)和産生連結的時間(也就是系統目前的時間)進行加密。
// 擷取系統目前時間
Date now = new Date();
String currentTime = "" + now.getTime();
// 重置密碼連結
String urlStr = "http://localhost:8080/LoveMovie/forgetPassword/resetPassword?key=";
String plainText = currentTime + "@" + userEmail; // 目前時間加上使用者郵箱 使用@進行連接配接二者,在大多數情況下不會産生歧義
String desKey = "LOVEMOIVE"; // des算法中的密鑰
String link = urlStr + DESUtil.encrypt(desKey, plainText); //加密後的連結
本來打算使用前幾篇自己實作的DES算法進行加密可不知道為什麼總是報錯數組越界,找了很久沒有找到問題所在,于是就又使用了别人寫好的DES(又做了一次搬運工~ (@_@))。如果想要對更加深入了解DES加密算法的話,可以看看我的寫的部落格[對稱密碼——DES加密算法](<https://www.cnblogs.com/myworld7/p/10596869.html>)(羞恥地推薦一波)
關于生成重置密碼連結的完整代碼我準備放在和驗證重置連結的代碼一起給出,因為生成連結是加密而驗證連結是解密,加解密一起看思路會更清晰一點。
驗證重置連結的合法性
這個的實作思路就很簡單了,提取連結中的參數key的值,然後使用des解密出明文。分割明文字元串為發送郵件的時間和使用者郵箱,将發送郵件的時間和目前系統時間進行比較內插補點若是小于2小時就響應使用者重置密碼界面,否則就提箱使用者該連結已失效。
相關demo位址
-
使用Java實作發送郵件
https://github.com/Sakuraxx/ToolDemos/tree/master/mail
-
使用DES加解密重置密碼連結
https://github.com/Sakuraxx/ToolDemos/tree/master/encrytion
小結
總觀這個發送郵件尋回密碼的功能還是比較簡單的,可能是因為做了搬運工的原因吧~~最後是放上發郵件和使用DES加解密連結這兩個子產品供,供大家在web項目中靈活使用。部落格中有任何問題,都歡迎交流哦~
參考:
- javamail發送郵件:https://lrh800300.iteye.com/blog/322090
- JavaMail API下載下傳位址:https://www.oracle.com/technetwork/java/javamail/javamail145-1904579.html
- "忘記密碼"功能過程及其實作細節:https://blog.csdn.net/shansusu/article/details/43311721
每天進步一點點,不要停止前進的腳步~