最近項目中需要用到忘記密碼的功能,因此,寫了這篇博客進行記錄。
首先需要用戶點擊忘記密碼,輸入用戶名和郵箱,兩者可以匹配,則向郵箱中發(fā)送條鏈接。eg:
點擊此鏈接進行密碼修改,有效期一個小時www.abc.com?ha=2HwBjxyI4WDRBUwewvo8xioRXszig1tf1Vx4dSMa5wI
點擊此鏈接進行重置密碼,后臺接受到ha參數(shù)的值,并對其進行解析,通過則可以進行密碼修改。
下邊主要解釋如何加密這個ha參數(shù),這里使用到了Base64進行加密和解密。
這里利用了一個jar包:commons-codec-1.8.jar(可以從官網(wǎng)或者maven下載)
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.8</version>
</dependency>
加密和解密工具類如下:
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;
}
}
/**
* 加密函數(shù)
* @param content 加密的內(nèi)容
* @param strKey 密鑰
* @return 返回二進制字符數(shù)組
* @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);
}
/**
* 解密函數(shù)
* @param src 加密過的二進制字符數(shù)組
* @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");
}
}
發(fā)送鏈接時,可以使用這個工具類,對參數(shù)進行加密和解密。我這個采用的方式是:對 用戶名+";"+郵箱+";"+時間戳 進行加密和解密
下面來一個測試類
@Test
public void test1() throws Exception{
long endTimes = System.currentTimeMillis()+3600*1000; //設(shè)置一小時有效時間。。
String para = "admin"+";"+"20@qq.com"+";"+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);
}
}
打印結(jié)果如下:
原文admin;20@qq.com;1541492725208
加密2HwBjxyI4WDRBUwewvo8xhcxtyeFhvB2tMG2W3QYwW0
解密:admin;20@qq.com;1541492725208
admin
20@qq.com
1541492725208
后臺可以通過拿到這個參數(shù)值,解密之后進行處理。例子如下:
public String toResetPwd(){
String ha = context.getParameter("ha");
if(null!=ha){
try {
//這里拿到參數(shù),進行解密操作
String decode = UrlUtils.deCryptAndDecode(ha);
String[] split = decode .split(";");
List<String> 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", "當(dāng)前鏈接已失效,請重新 后去重置密碼鏈接!");
}else{
context.setRequestAttribute("personname", personname);
context.setRequestAttribute("email", email);
}
}
} catch (Exception e) {
e.printStackTrace();
context.setRequestAttribute("errorMsg", "鏈接無效!");
}
}
return "SUCCESS";
}
到這里,就可以結(jié)束了。