最近项目中需要用到忘记密码的功能,因此,写了这篇博客进行记录。
首先需要用户点击忘记密码,输入用户名和邮箱,两者可以匹配,则向邮箱中发送条链接。eg:
点击此链接进行密码修改,有效期一个小时www.abc.com?ha=2HwBjxyI4WDRBUwewvo8xioRXszig1tf1Vx4dSMa5wI
点击此链接进行重置密码,后台接受到ha参数的值,并对其进行解析,通过则可以进行密码修改。
下边主要解释如何加密这个ha参数,这里使用到了Base64进行加密和解密。
这里利用了一个jar包:commons-codec-1.8.jar(可以从官网或者maven下载)
commons-codec
commons-codec
1.8
加密和解密工具类如下:
package com.ocean.utils;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.SecureRandom;
public class UrlUtils {
private static final String KEY = "myoMwO6qPt&3AD";
private static final Logger LOGGER = LoggerFactory.getLogger(UrlUtils.class);
public static String enCryptAndEncode(String content) {
try {
byte[] sourceBytes = enCryptAndEncode(content, KEY);
return Base64.encodeBase64URLSafeString(sourceBytes);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
return content;
}
}
/**
* 加密函数
* @param content 加密的内容
* @param strKey 密钥
* @return 返回二进制字符数组
* @throws Exception
*/
public static byte[] enCryptAndEncode(String content, String strKey) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128, new SecureRandom(strKey.getBytes()));
SecretKey desKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, desKey);
return cipher.doFinal(content.getBytes("UTF-8"));
}
public static String deCryptAndDecode(String content) throws Exception {
byte[] targetBytes = Base64.decodeBase64(content);
return deCryptAndDecode(targetBytes, KEY);
}
/**
* 解密函数
* @param src 加密过的二进制字符数组
* @param strKey 密钥
* @return
* @throws Exception
*/
public static String deCryptAndDecode(byte[] src, String strKey) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128, new SecureRandom(strKey.getBytes()));
SecretKey desKey = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, desKey);
byte[] cByte = cipher.doFinal(src);
return new String(cByte, "UTF-8");
}
}
发送链接时,可以使用这个工具类,对参数进行加密和解密。我这个采用的方式是:对 用户名+";"+邮箱+";"+时间戳 进行加密和解密
下面来一个测试类
@Test
public void test1() throws Exception{
long endTimes = System.currentTimeMillis()+3600*1000; //设置一小时有效时间。。
String para = "admin"+";"+"[email protected]"+";"+endTimes;
System.out.println("原文"+para);
String encode = UrlUtils.enCryptAndEncode(para);
System.out.println("加密"+encode); //http://www.cnblogs.com/haha12/p/4345070.html
String old = UrlUtils.deCryptAndDecode(encode);
System.out.println("解密:"+old);
String[] split = old.split(";");
for (String string : split) {
System.out.println(string);
}
}
打印结果如下:
原文admin;[email protected];1541492725208
加密2HwBjxyI4WDRBUwewvo8xhcxtyeFhvB2tMG2W3QYwW0
解密:admin;[email protected];1541492725208
admin
1541492725208
后台可以通过拿到这个参数值,解密之后进行处理。例子如下:
public String toResetPwd(){
String ha = context.getParameter("ha");
if(null!=ha){
try {
//这里拿到参数,进行解密操作
String decode = UrlUtils.deCryptAndDecode(ha);
String[] split = decode .split(";");
List list = Arrays.asList(split);
if(null!=list && list.size()>0){
String personname = (String)list.get(0);
String email = (String)list.get(1);
long entimes = Long.parseLong((String)list.get(2));
long curtime = System.currentTimeMillis();
if(entimes<=curtime){ //判断有效期
context.setRequestAttribute("errorMsg", "当前链接已失效,请重新 后去重置密码链接!");
}else{
context.setRequestAttribute("personname", personname);
context.setRequestAttribute("email", email);
}
}
} catch (Exception e) {
e.printStackTrace();
context.setRequestAttribute("errorMsg", "链接无效!");
}
}
return "SUCCESS";
}
到这里,就可以结束了。