关于邮件找回密码的原理思想为:
1.用户申请找回密码功能,服务器将会发送一个url地址到用户注册的邮箱中去。
2.用户打开邮箱点击url地址跳转到相应的网页中修改密码。
3.修改完密码就可以重新登录了。
这些过程中最重要的就是url地址安全的问题了,如何才能保证url地址不会被篡改就是核心问题了。
下面是我对于这个问题的一些解决方案,如有不足或有问题请和及时我联系QQ:208017534
步骤:
1.搭建邮件服务器(这里我使用的是James服务器,如果这方面有什么不懂的可以看我以前写的博客内容)。
2.生成url地址:
这里生成url地址有三大要素:用户账号(account)+过期时间(outtime)+随机值(key),然后通过md5将这些要素进行散列加密生成sid值。然后将outtime,sid,account存入数据库中进行邮件url地址是否有效的验证。
数据库截图:
关键代码: 生成随机值的工具类:
package example.utils;
public class RandomUtils {
//获取m~n范围内的整数
public static int getRandom(int m,int n){
int random=(int)(Math.random()*(n-m))+m;
return random;
}
//获取位数为n的随机数
public static int getRandom(int length){
int m=getNumber(length);
int n=m*10-1;
int random=(int)(Math.random()*(n-m))+m;
return random;
}
public static int getNumber(int n){
if(n<1){
n=1;
}
if(n==1){
return 1;
}else{
n=n-1;
return 10*getNumber(n);
}
}
}
Md5检验的工具类:
package example.encrypt;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Md5Encrypt {
/**利用MD5进行加密
* @param str 待加密的字符串
* @return 加密后的字符串
*/
public static String EncoderByMd5(String str){
//确定计算方法
MessageDigest md5= null;
String result="";
try {
md5 = MessageDigest.getInstance("MD5");
result=new BASE64Encoder().encode(md5.digest(str.getBytes("utf-8")));
} catch (Exception e) {
e.printStackTrace();
}
//加密后的字符串
return result;
}
}
生成url核心代码:
业务层代码:
//找回密码
public Object findPassowrd(String basePath,String account){
Manage manage= manageDao.findByAccount(account);
String code,info,result;
if(manage==null){
code="001";
info="Account does not exist";
result="";
}else{
//生成邮件url唯一地址
String key= RandomUtils.getRandom(6)+"";
Timestamp outDate = new Timestamp(System.currentTimeMillis()+(long)(30*60*1000));//30分钟后过期 //忽略毫秒数
long outtimes=outDate.getSysUpTime();
String sid=account+"&"+key+"&"+outtimes;
MailRetrieve mailRetrieve=new MailRetrieve(account,Md5Encrypt.EncoderByMd5(sid),outtimes);
MailRetrieve findMailRetrieve=mailRetrieveDao.findByAccount(account);
if(findMailRetrieve!=null){
mailRetrieveDao.delete(findMailRetrieve);
}
mailRetrieveDao.save(mailRetrieve);
result = basePath+"user/reset_password?sid="+Md5Encrypt.EncoderByMd5(sid)+"&userName="+account;
code="005";
info="Email retrieve password";
}
return JsonUtils.toJson(code,info,result);
}
控制层的代码:
@RequestMapping("/back")
@ResponseBody
public Object backManage(HttpServletRequest request,String account){
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
return manageService.findPassowrd(basePath,account);
}
邮件实体类代码:
package example.entity;
import javax.persistence.*;
@Entity
@Table(name = "myweb_mail_retrieve")
public class MailRetrieve{
private static final long serialVersionUID = -1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "account", nullable = true, length = 20)
private String account;
@Column(name = "sid", nullable = true, length = 25)
private String sid;
@Column(name = "out_time", nullable = true, length = 20)
private long outTime;
public MailRetrieve() {
}
public MailRetrieve(String account, String sid, long outTime) {
this.account = account;
this.sid = sid;
this.outTime = outTime;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public MailRetrieve(String account) {
this.account = account;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public long getOutTime() {
return outTime;
}
public void setOutTime(long outTime) {
this.outTime = outTime;
}
}
3.通过James邮件服务器将url地址发送到用户邮箱中(具体过程看以前的案例介绍)。
4.点击url地址,服务器进行邮件url地址检验,检验完跳转到相应的界面中进行处理:
业务层代码:
//邮件U找回密码URL校验
public Object verifyMail(String sid,String account){
String code,info;
boolean result=false;
MailRetrieve mailRetrieve=mailRetrieveDao.findByAccount(account);
long outTime=mailRetrieve.getOutTime();
Timestamp outDate = new Timestamp(System.currentTimeMillis());
long nowTime=outDate.getSysUpTime();
System.out.println("nowTime:"+nowTime);
if(outTime<=nowTime){
code="006";
info="verifyMail time is overdue";
}else if("".equals(sid)){
code="007";
info="sid is incomplete content";
}else if(!sid.equals(mailRetrieve.getSid())){
code="008";
info="sid is error";
}else{
code="000";
info="no error";
result=true;
}
return JsonUtils.toJson(code,info,result);
}
控制层代码:
@RequestMapping("/verify")
@ResponseBody
public Object verifyMail(String sid,String account){
return manageService.verifyMail(sid,account);
}
这整个过程中需要注意的有:1时间是否过期要判断好、2保存邮件url信息的时候要注意数据库中是否有这个信息存在,如果存在则删除重新添加。
上面介绍的只是部分的核心代码,如果大家想要全部的源代码或者对本文内容有啥异议的都可以联系我QQ:208017534 欢迎打扰!!!