本文實例為大家分享了java實現郵件找回密碼功能的具體代碼,供大家參考,具體內容如下
1、有個需求就是,忘記密碼后通過郵箱找回。現在的系統在注冊的時候都會強制輸入郵箱,其一目的就是 通過郵件綁定找回,可以進行密碼找回。通過java發送郵件的功能我就不說了,重點講找回密碼。
2、參考別人的思路:發送郵件→請求郵件里的url→驗證url→{驗證成功修改密碼,不成功跳轉到失敗頁面}
重點就是如何生成這個url和如何解析這個url.
需要注意的是一個url只能修改一次密碼,當同一帳號發送多封郵件,只有最后一封郵件的url
3、加密能防止偽造攻擊,一次url只能驗證一次,并且綁定了用戶。生成url: 可以用uuid生成隨機密鑰。
數字簽名 = md5(用戶名+'$'+過期時間+‘$'+密鑰key)
數據庫字段(用戶名(主鍵),密鑰key,過期時間)
url參數(用戶名,數字簽名) ,密鑰key的生成:在每一個用戶找回密碼時候為這個用戶生成一個密鑰key ,url example: http://localhost:8080/user/reset_password?sid=d622d6a23fbf86ffe696b593d55351a54aeaea77&username=test4
生成過期時間,生成數字簽名,生成url,發送郵件.saveorupdate(用戶名,密鑰key,過期時間)
以下為springmvc代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
@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 ){ //用戶名不存在 msg = "用戶名不存在,你不會忘記用戶名了吧?" ; map.put( "msg" ,msg); return map; } try { string secretkey= uuid.randomuuid().tostring(); //密鑰 timestamp outdate = new timestamp(system.currenttimemillis()+ 30 * 60 * 1000 ); //30分鐘后過期 long date = outdate.gettime()/ 1000 * 1000 ; //忽略毫秒數 users.setvalidatacode(secretkey); users.setregisterdate(outdate); userservice.update(users); //保存到數據庫 string key = users.getusername()+ "$" +date+ "$" +secretkey; string digitalsignature = md5.md5encode(key); //數字簽名 string emailtitle = "有方云密碼找回" ; 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 = "請勿回復本郵件.點擊下面的鏈接,重設密碼<br/><a href=" +resetpasshref + " rel=" external nofollow " target='_blank'>點擊我重新設置密碼</a>" + "<br/>tips:本郵件超過30分鐘,鏈接將會失效,需要重新申請'找回密碼'" +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; } |
找回鏈接已經發到郵箱了。進入郵箱點開鏈接
以下為鏈接檢驗代碼,驗證通過 跳轉到修改密碼界面,否則跳轉到失敗界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
@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= "鏈接不完整,請重新生成" ; model.addobject( "msg" ,msg) ; loginfo(username, "找回密碼鏈接失效" ); return model; } users users = userservice.finduserbyname(username); if (users == null ){ msg = "鏈接錯誤,無法找到匹配用戶,請重新申請找回密碼." ; model.addobject( "msg" ,msg) ; loginfo(username, "找回密碼鏈接失效" ); return model; } timestamp outdate = users.getregisterdate(); if (outdate.gettime() <= system.currenttimemillis()){ //表示已經過期 msg = "鏈接已經過期,請重新申請找回密碼." ; model.addobject( "msg" ,msg) ; loginfo(username, "找回密碼鏈接失效" ); return model; } string key = users.getusername()+ "$" +outdate.gettime()/ 1000 * 1000 + "$" +users.getvalidatacode(); //數字簽名 string digitalsignature = md5.md5encode(key); system.out.println(key+ "\t" +digitalsignature); if (!digitalsignature.equals(sid)) { msg = "鏈接不正確,是否已經過期了?重新申請吧" ; model.addobject( "msg" ,msg) ; loginfo(username, "找回密碼鏈接失效" ); return model; } model.setviewname( "user/reset_password" ); //返回到修改密碼的界面 model.addobject( "username" ,username); return model; } |
補充1:timestamp類型對象在保存到數據的時候 毫秒精度會丟失。比如:2013-10-08 10:29:10.234 存到mysql數據庫的時候 變成 2013-10-08 10:29:10.0。時間變得不相同了,sid 匹配的時候不會相等。 所以我做了忽略精度的操作。
補充2:解決linux下面title中文亂碼
1
2
3
4
|
sun.misc.base64encoder enc = new sun.misc.base64encoder(); mailmessage.setsubject(mimeutility.encodetext(mailinfo.getsubject(), "utf-8" , "b" )); //解決linux郵件title亂碼 |
補充3:怎么不直接把sid插入到user表呢。驗證的時候直接比較sid就ok了。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/Jerome_s/article/details/43236505