本次以密碼找回使用郵箱方式找回爲例
步驟:可能相互調用有點亂,但是我寫的很清楚,應該不難看懂
1、獲取用戶名和郵箱,寫好郵件內容,發送郵件:
2、上一步調用的郵件發送方法,在這裏實現
3、數據加密,第一步中用到了加密。第四步用到了解密(這裏都是被調用的方法):
4、由於發送的鏈接定位到是重置頁面,也就是他給你隨機分配一個新密碼,你可以拿着這個新密碼重新登陸,然後去修改,這裏主要是講如何將獲得加密數據解密,並返回隨機密碼
郵件發送需要兩個jar包要引進,保存在百度雲資源裏,連接如下:
jar包 提取碼:cbsu
1、獲取用戶名和郵箱,寫好郵件內容,發送郵件:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
String name=request.getParameter("username");
String email=request.getParameter("email");
Map<String, Object> res = new HashMap<>();
String error=null;
if ("".equals(email)) {
error="郵箱不能爲空";
}
else {
//我的用戶類User
User user= null;
try {
//在我的用戶數據庫表中通過名字查找用戶是否存在
user = UserDao.getByName(name);
System.out.println(user);
if (user == null) {
error="該用戶不存在";
}else
{
//如果用戶存在,還要查看對應用戶的email是否一致
String emails=user.getEmail();
if(!emails.equals(email)){
error="郵箱不正確";
}else{
//正式編寫郵件內容
//計算token
String token=String.format("%s,%s,%s,%s",user.getUid(),user.getUsername(),user.getEmail(),System.currentTimeMillis());
//加密,這裏調用下面的SecureUtils類中的加密算法
token = SecureUtils._3DES_encode(emailKEY, token.getBytes());
//計算url,先獲取你找回密碼的URL地址,再加上你的加密token(爲了防止有人冒充你的身份信息)
String url=request.getRequestURL().toString();
url=url.replace(request.getRequestURI(),"");
url=url+request.getContextPath()+"/Reset?token="+token;
//發送郵件,這裏的 MailUtils.sendMail在下面
System.out.println(email+" "+token);
//第二個參數爲context,自定義郵件內容,
MailUtils.sendMail(user.getEmail(),"重置鏈接:"+url);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//將錯誤信息返回給去前端,沒有錯誤的話返回null
res.put("mess",error);
System.out.println("返回信息"+error);
response.getWriter().write(new Gson().toJson(res));
}
}
2、上一步調用的郵件發送方法,在這裏實現
package utils;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Date;
import java.util.Properties;
public class MailUtils {
public static final String HOST ="smtp.xxxx.com";//郵件服務器,這裏怎麼寫自行百度,根據你發郵件的郵件服務器不同
public static final String USERNAME ="[email protected]";//賬戶用戶名
public static final String PASSWORD ="Qhj12345";//密碼
public static boolean sendMail(String to, String content) {
//設置屬性
Properties props = new Properties();
props.put("mail.smtp.HOST", HOST);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "25");
// 環境信息
Session session = Session.getDefaultInstance(props,
new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
// 在session中設置賬戶信息,Transport發送郵件時會使用
return new PasswordAuthentication(USERNAME, PASSWORD);
}
});
try {
//郵件
MimeMessage msg = new MimeMessage(session);
//發件人
msg.setFrom(new InternetAddress(USERNAME));
//設置收件人
msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(to));
msg.setSubject("重置密碼");
//整封郵件的MIME消息體
Multipart mp = new MimeMultipart();
MimeBodyPart mbpContent = new MimeBodyPart();//附件
mbpContent.setContent(content, "text/html;charset=utf-8");
mp.addBodyPart(mbpContent);
msg.setContent(mp);
msg.setSentDate(new Date());
msg.saveChanges();
//發送郵件
Transport transport = session.getTransport("smtp");
transport.connect(HOST, USERNAME, PASSWORD);
transport.sendMessage(msg, msg.getAllRecipients());
transport.close();
} catch (Exception mex) {
mex.printStackTrace();
return false;
}
return true;
}
}
3、數據加密,第一步中用到了加密。第四步用到了解密(這裏都是被調用的方法):
package utils;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.UUID;
public class SecureUtils {
private static final String Iv = "\0\0\0\0\0\0\0\0";
private static final String Transformation = "DESede/CBC/PKCS5Padding";
public static String fixedHexString(byte[] hashBytes) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < hashBytes.length; ++i) {
sb.append(Integer.toString((hashBytes[i] & 255) + 256, 16).substring(1));
}
return sb.toString();
}
//des加密
public static String _3DES_encode(byte[] key, byte[] data) {
SecretKey deskey = new SecretKeySpec(key, "DESede");
IvParameterSpec iv = new IvParameterSpec(Iv.getBytes());
try {
Cipher c1 = Cipher.getInstance(Transformation);
c1.init(Cipher.ENCRYPT_MODE, deskey, iv);
byte[] re = c1.doFinal(data);
return fixedHexString(re);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//解密
public static String _3DES_decode(byte[] key, byte[] data) {
SecretKey deskey = new SecretKeySpec(key, "DESede");
IvParameterSpec iv = new IvParameterSpec(Iv.getBytes());
try {
Cipher c1 = Cipher.getInstance(Transformation);
c1.init(Cipher.DECRYPT_MODE, deskey, iv);
byte[] re = c1.doFinal(data);
return new String(re);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] hexstr2bytearray(String str) {
byte[] re = new byte[str.length() / 2];
for (int i = 0; i < re.length; i++) {
int r = Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
re[i] = (byte) r;
}
return re;
}
public static String getMD5(String str) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes());
return new BigInteger(1, md.digest()).toString(16);
}
//生成隨機數字和字母,
public static String getStringRandom(int length) {
String val = "";
Random random = new Random();
//參數length,表示生成幾位隨機數
for (int i = 0; i < length; i++) {
String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
//輸出字母還是數字
if ("char".equalsIgnoreCase(charOrNum)) {
//輸出是大寫字母還是小寫字母
int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
val += (char) (random.nextInt(26) + temp);
} else if ("num".equalsIgnoreCase(charOrNum)) {
val += String.valueOf(random.nextInt(10));
}
}
return val;
}
public static String getUUID() {
UUID uuid = UUID.randomUUID();
String str = uuid.toString();
String uuidStr = str.replace("-", "");
return uuidStr;
}
}
4、由於發送的鏈接定位到是重置頁面,也就是他給你隨機分配一個新密碼,你可以拿着這個新密碼重新登陸,然後去修改,這裏主要是講如何將獲得加密數據解密,並返回隨機密碼
package servlet;
import dao.UserDao;
import entity.User;
import utils.SecureUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name = "Reset",urlPatterns = "/Reset")
public class Reset extends HttpServlet{
private byte[] emailKEY = "yfHyN!5nyvtfMs9nF1P2QRkx".getBytes();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String token=request.getParameter("token");
PrintWriter out=response.getWriter();
if("".equals(token)){
out.println("請不要直接訪問這個鏈接!!!");
}
if (token.length() < 10) {
out.println("非法token");
}
try {
//解密
token = SecureUtils._3DES_decode(emailKEY, SecureUtils.hexstr2bytearray(token));
if (token == null) {
out.println("非法token");
}
//這裏的值的個數,是根據你第一步創建token是攜帶了一個信息決定的,我帶了四個
String[] tmp = token.split(",", 4);
if (tmp.length != 4 || tmp[0].length() == 0 || tmp[1].length() == 0 || tmp[2].length() == 0||tmp[3].length()==0) {
out.println("非法token");
}
long time = Long.parseLong(tmp[3]);
if (System.currentTimeMillis() - time > 10*60*1000) {
out.println("該重置鏈接已經超時");
}
String uname=tmp[1];
User user= UserDao.getByName(uname);
if(user==null) {
out.println("用戶不存在");
}
if(tmp[1].equals(user.getUsername())&&tmp[2].equals(user.getEmail())){
String password=SecureUtils.getStringRandom(6);
UserDao.updatePassword(uname,password);
out.println("你的新密碼是:"+password);
}else{
out.println("驗證失敗!!請重新驗證!!");
}
} catch (Throwable e) {
out.println("非法token");
}
}
}
這裏只是舉例借鑑,實際應用到自己項目還是要修改的,給出參考思路,對於第二、三步可以直接使用粘貼,因爲這是我直接拿自己項目寫的,所以1,4步稍有不同