一、帳戶激活
在很多時候,在某些網站註冊一個用戶之後,網站會給這個用戶註冊時填寫的email地址發送一封帳戶激活郵件,這封郵件的內容就是一個激活帳戶的鏈接和一段簡短的文字描述,如果用戶沒有去郵箱將帳戶激活,可能在使用網站的某些功能時就會受到限制,比如不能發貼、下載資料、評論等限制。這麼做的原因應該是爲了保證帳戶的安全性和郵箱的有效性,以後網站如果有什麼活動、資訊或系統安全通知等,可以在第一時間通知到用戶。比如我在奇藝視頻網站註冊一個帳號之後,它就會往我註冊時填寫的郵箱中發一封帳戶激活的郵件,郵件中有一個激活的鏈接,點擊它就可以將你的帳戶激活。如下圖所示:
這個功能是怎麼做到的呢,其實實現也是很簡單的,說白了就是一個Update操作。
實現思路:當一個用戶註冊成功之後,系統向用戶註冊時提供的email地址發送一封郵件,郵件的內容是一個激活帳戶的鏈接和一段簡短的文字描述,這個鏈接的功能就是將這個帳戶的狀態修改成激活狀態。這個功能的重點在於如何生成這個激活帳戶的鏈接。直接可以聯想到的方法就是建一個Servlet,Servlet接收一個用戶名參數,Servlet拿到用戶名參數之後,到數據庫把這條記錄load出來,做一次update操作即可。但是這樣做會有風險,比如有人想在你的網站上搞破壞,註冊時他填的email地址就是亂填的,這個Email地址可能根本就收不到郵件(但符合email格式),註冊完成之後,然後在瀏覽器地址欄輸入網站之前發送的帳戶激活鏈接,並加上新註冊的用戶名參數,這樣一來就跳過了去郵箱激活的步聚,時間久了,庫中可能會留下許多無效的email地址和帳戶。爲了避免這個問題,解決方案是在用戶註冊成功之後,在發送激活帳戶的鏈接中加一個隨機碼,這個隨機碼是將用戶名和一個隨機數用md5加密後的一串16進制字符串,每次用戶在激活帳戶的時候,都驗證這個隨機碼是否和註冊時發送的一致,這樣就可以避免人爲的修改激活鏈接達到帳戶激活的功能。
二、忘記密碼
當你在某網站註冊一個帳戶之後,發現這個帳戶很久沒用了,密碼也忘記了,如果還記得之前註冊時填寫的Email,那就可以向你的email中發一個重設密碼的鏈接,就可以重新設置你的密碼。大部份網站一般都提供了根據Email找回密碼的功能。實現此功能的思路:在登錄界面添加一個“忘記密碼“的鏈接,用戶點擊進去之後,輸入用戶名或Email,系統根據用戶名或Email找出用戶信息,並生成一個重新設置密碼的鏈接發送到用戶的郵箱中(生成鏈接的方式和生成帳戶激活鏈接的方式一樣),用戶在郵箱中點擊重設密碼的鏈接,根據提示進入密碼重設頁面,重新輸入新的密碼即可。
功能實現步聚(帳號激活):
1、用戶註冊頁面
- <form action="${pageContext.request.contextPath}/register" method="post">
- 用戶名:<input type="text" name="userName" value="${param.userName}"><span class="error">${errors.userName}</span><br/>
- 密碼:<input type="password" name="password" ><span class="error">${errors.password}</span><br/>
- 確認密碼:<input type="password" name="password2"><span class="error">${errors.password2}</span><br/>
- email:<input type="text" name="email" value="${param.email}"><span class="error">${errors.email}</span><br/>
- <input type="submit" value="註冊">
- </form>
<form action="${pageContext.request.contextPath}/register" method="post">
用戶名:<input type="text" name="userName" value="${param.userName}"><span class="error">${errors.userName}</span><br/>
密碼:<input type="password" name="password" ><span class="error">${errors.password}</span><br/>
確認密碼:<input type="password" name="password2"><span class="error">${errors.password2}</span><br/>
email:<input type="text" name="email" value="${param.email}"><span class="error">${errors.email}</span><br/>
<input type="submit" value="註冊">
</form>
2、處理註冊請求的Servlet(RegisterServlet)
- package org.study.accountactivate.web.servlet;
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.Map;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.study.accountactivate.dao.UserDao;
- import org.study.accountactivate.dao.impl.UserDaoImpl;
- import org.study.accountactivate.domail.User;
- import org.study.accountactivate.util.EmailUtils;
- /**
- * 用戶註冊
- */
- public class RegisterServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- private UserDao userDao = UserDaoImpl.getInstance();
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- doPost(request, response);
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String userName = request.getParameter("userName");
- String password = request.getParameter("password");
- String password2 = request.getParameter("password2");
- String email = request.getParameter("email");
- Map<String, String> errors = new HashMap<String,String>();
- if (userName == null || "".equals(userName)) {
- errors.put("userName", "用戶名不能爲空!");
- } else if (userName != null && userDao.findUserByName(userName) != null) {
- errors.put("userName", "該用戶已註冊!");
- }
- if (password == null || "".equals(password)) {
- errors.put("password","密碼不能爲空!");
- } else if (password != null && password.length() < 3) {
- errors.put("password","密碼長度不能低於3位!");
- }
- if (password2 == null || "".equals(password2)) {
- errors.put("password2", "確認密碼不能爲空!");
- } else if (password2 != null && !password2.equals(password)) {
- errors.put("password2", "兩次輸入的密碼不一致!");
- }
- if (email == null || "".equals(email)) {
- errors.put("email", "email不能爲空!");
- } else if (email != null && !email.matches("[0-9a-zA-Z_-]+@[0-9a-zA-Z_-]+\\.[0-9a-zA-Z_-]+(\\.[0-9a-zA-Z_-])*")) {
- errors.put("email", "email格式不正確!");
- }
- if (!errors.isEmpty()) {
- request.setAttribute("errors", errors);
- request.getRequestDispatcher("/registerUI").forward(request, response);
- return;
- }
- User user = new User();
- user.setUserName(userName);
- user.setPassword(password);
- user.setEmail(email);
- user.setActivated(false);
- userDao.addUser(user);
- // 註冊成功後,發送帳戶激活鏈接
- EmailUtils.sendAccountActivateEmail(user);
- // 註冊成功直接將當前用戶保存到session中
- request.getSession().setAttribute("user", user);
- request.getRequestDispatcher("/WEB-INF/pages/registerSuccess.jsp").forward(request,response);
- }
- }
package org.study.accountactivate.web.servlet;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.study.accountactivate.dao.UserDao;
import org.study.accountactivate.dao.impl.UserDaoImpl;
import org.study.accountactivate.domail.User;
import org.study.accountactivate.util.EmailUtils;
/**
* 用戶註冊
*/
public class RegisterServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private UserDao userDao = UserDaoImpl.getInstance();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
String password2 = request.getParameter("password2");
String email = request.getParameter("email");
Map<String, String> errors = new HashMap<String,String>();
if (userName == null || "".equals(userName)) {
errors.put("userName", "用戶名不能爲空!");
} else if (userName != null && userDao.findUserByName(userName) != null) {
errors.put("userName", "該用戶已註冊!");
}
if (password == null || "".equals(password)) {
errors.put("password","密碼不能爲空!");
} else if (password != null && password.length() < 3) {
errors.put("password","密碼長度不能低於3位!");
}
if (password2 == null || "".equals(password2)) {
errors.put("password2", "確認密碼不能爲空!");
} else if (password2 != null && !password2.equals(password)) {
errors.put("password2", "兩次輸入的密碼不一致!");
}
if (email == null || "".equals(email)) {
errors.put("email", "email不能爲空!");
} else if (email != null && !email.matches("[0-9a-zA-Z_-]+@[0-9a-zA-Z_-]+\\.[0-9a-zA-Z_-]+(\\.[0-9a-zA-Z_-])*")) {
errors.put("email", "email格式不正確!");
}
if (!errors.isEmpty()) {
request.setAttribute("errors", errors);
request.getRequestDispatcher("/registerUI").forward(request, response);
return;
}
User user = new User();
user.setUserName(userName);
user.setPassword(password);
user.setEmail(email);
user.setActivated(false);
userDao.addUser(user);
// 註冊成功後,發送帳戶激活鏈接
EmailUtils.sendAccountActivateEmail(user);
// 註冊成功直接將當前用戶保存到session中
request.getSession().setAttribute("user", user);
request.getRequestDispatcher("/WEB-INF/pages/registerSuccess.jsp").forward(request,response);
}
}
3、激活帳戶的Servlet(ActivateAccountServle)
- package org.study.accountactivate.web.servlet;
- import java.io.IOException;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.study.accountactivate.dao.UserDao;
- import org.study.accountactivate.dao.impl.UserDaoImpl;
- import org.study.accountactivate.domail.User;
- import org.study.accountactivate.util.GenerateLinkUtils;
- /**
- * 帳戶激活
- */
- public class ActivateAccountServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String idValue = request.getParameter("id");
- int id = -1;
- try {
- id = Integer.parseInt(idValue);
- } catch (NumberFormatException e) {
- throw new RuntimeException("無效的用戶!");
- }
- UserDao userDao = UserDaoImpl.getInstance();
- User user = userDao.findUserById(id);// 得到要激活的帳戶
- user.setActivated(GenerateLinkUtils.verifyCheckcode(user, request));// 校驗驗證碼是否和註冊時發送的一致,以此設置是否激活該帳戶
- userDao.updateUser(user);
- request.getSession().setAttribute("user", user);
- request.getRequestDispatcher("/accountActivateUI").forward(request, response);
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- doGet(request, response);
- }
- }
package org.study.accountactivate.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.study.accountactivate.dao.UserDao;
import org.study.accountactivate.dao.impl.UserDaoImpl;
import org.study.accountactivate.domail.User;
import org.study.accountactivate.util.GenerateLinkUtils;
/**
* 帳戶激活
*/
public class ActivateAccountServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String idValue = request.getParameter("id");
int id = -1;
try {
id = Integer.parseInt(idValue);
} catch (NumberFormatException e) {
throw new RuntimeException("無效的用戶!");
}
UserDao userDao = UserDaoImpl.getInstance();
User user = userDao.findUserById(id);// 得到要激活的帳戶
user.setActivated(GenerateLinkUtils.verifyCheckcode(user, request));// 校驗驗證碼是否和註冊時發送的一致,以此設置是否激活該帳戶
userDao.updateUser(user);
request.getSession().setAttribute("user", user);
request.getRequestDispatcher("/accountActivateUI").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
4、操作用戶的DAO接口與實現類(UserDao和UserDaoImpl類)
- package org.study.accountactivate.dao;
- import org.study.accountactivate.domail.User;
- public interface UserDao {
- void addUser(User user);
- void updateUser(User user);
- User findUserById(int id);
- User findUserByName(String userName);
- User findUserByNameOrEmail(String nameOrEmail);
- }
- package org.study.accountactivate.dao.impl;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.UUID;
- import org.study.accountactivate.dao.UserDao;
- import org.study.accountactivate.domail.User;
- public class UserDaoImpl implements UserDao {
- private static UserDaoImpl instance = new UserDaoImpl();
- private UserDaoImpl() {}
- public static UserDaoImpl getInstance() {
- return instance;
- }
- Map<Integer,User> users = new HashMap<Integer, User>();
- int nextId = 1;
- @Override
- public void addUser(User user) {
- user.setId(nextId++);
- user.setRandomCode(UUID.randomUUID().toString());
- users.put(user.getId(), user);
- }
- @Override
- public void updateUser(User user) {
- users.put(user.getId(), user);
- }
- @Override
- public User findUserById(int id) {
- return users.get(id);
- }
- @Override
- public User findUserByName(String userName) {
- Collection<User> userValues = users.values();
- for (Iterator<User> iterator = userValues.iterator();iterator.hasNext();) {
- User user = iterator.next();
- if (user.getUserName().equals(userName)) {
- return user;
- }
- }
- return null;
- }
- @Override
- public User findUserByNameOrEmail(String nameOrEmail) {
- Collection<User> userValues = users.values();
- for(Iterator<User> iterator = userValues.iterator();iterator.hasNext();) {
- User user = iterator.next();
- if (user.getEmail().equals(nameOrEmail) || user.getUserName().equals(nameOrEmail)) {
- return user;
- }
- }
- return null;
- }
- }
package org.study.accountactivate.dao;
import org.study.accountactivate.domail.User;
public interface UserDao {
void addUser(User user);
void updateUser(User user);
User findUserById(int id);
User findUserByName(String userName);
User findUserByNameOrEmail(String nameOrEmail);
}
package org.study.accountactivate.dao.impl;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import org.study.accountactivate.dao.UserDao;
import org.study.accountactivate.domail.User;
public class UserDaoImpl implements UserDao {
private static UserDaoImpl instance = new UserDaoImpl();
private UserDaoImpl() {}
public static UserDaoImpl getInstance() {
return instance;
}
Map<Integer,User> users = new HashMap<Integer, User>();
int nextId = 1;
@Override
public void addUser(User user) {
user.setId(nextId++);
user.setRandomCode(UUID.randomUUID().toString());
users.put(user.getId(), user);
}
@Override
public void updateUser(User user) {
users.put(user.getId(), user);
}
@Override
public User findUserById(int id) {
return users.get(id);
}
@Override
public User findUserByName(String userName) {
Collection<User> userValues = users.values();
for (Iterator<User> iterator = userValues.iterator();iterator.hasNext();) {
User user = iterator.next();
if (user.getUserName().equals(userName)) {
return user;
}
}
return null;
}
@Override
public User findUserByNameOrEmail(String nameOrEmail) {
Collection<User> userValues = users.values();
for(Iterator<User> iterator = userValues.iterator();iterator.hasNext();) {
User user = iterator.next();
if (user.getEmail().equals(nameOrEmail) || user.getUserName().equals(nameOrEmail)) {
return user;
}
}
return null;
}
}
5、發送Email的工具類(EmailUtils,用於發送帳戶激活鏈接和密碼重置鏈接)
- package org.study.accountactivate.util;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Date;
- import java.util.Properties;
- import javax.mail.Authenticator;
- import javax.mail.Message.RecipientType;
- import javax.mail.PasswordAuthentication;
- import javax.mail.Session;
- import javax.mail.Transport;
- import javax.mail.internet.InternetAddress;
- import javax.mail.internet.MimeMessage;
- import org.study.accountactivate.domail.User;
- public class EmailUtils {
- private static final String FROM = "[email protected]";
- /**
- * 註冊成功後,向用戶發送帳戶激活鏈接的郵件
- * @param user 未激活的用戶
- */
- public static void sendAccountActivateEmail(User user) {
- Session session = getSession();
- MimeMessage message = new MimeMessage(session);
- try {
- message.setSubject("帳戶激活郵件");
- message.setSentDate(new Date());
- message.setFrom(new InternetAddress(FROM));
- message.setRecipient(RecipientType.TO, new InternetAddress(user.getEmail()));
- message.setContent("<a href='" + GenerateLinkUtils.generateActivateLink(user)+"'>點擊激活帳戶</a>","text/html;charset=utf-8");
- // 發送郵件
- Transport.send(message);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 發送重設密碼鏈接的郵件
- */
- public static void sendResetPasswordEmail(User user) {
- Session session = getSession();
- MimeMessage message = new MimeMessage(session);
- try {
- message.setSubject("找回您的帳戶與密碼");
- message.setSentDate(new Date());
- message.setFrom(new InternetAddress(FROM));
- message.setRecipient(RecipientType.TO, new InternetAddress(user.getEmail()));
- message.setContent("要使用新的密碼, 請使用以下鏈接啓用密碼:<br/><a href='" + GenerateLinkUtils.generateResetPwdLink(user) +"'>點擊重新設置密碼</a>","text/html;charset=utf-8");
- // 發送郵件
- Transport.send(message);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static Session getSession() {
- Properties props = new Properties();
- props.setProperty("mail.transport.protocol", "smtp");
- props.setProperty("mail.smtp.host", "smtp.163.com");
- props.setProperty("mail.smtp.port", "25");
- props.setProperty("mail.smtp.auth", "true");
- Session session = Session.getInstance(props, new Authenticator() {
- @Override
- protected PasswordAuthentication getPasswordAuthentication() {
- String password = null;
- InputStream is = EmailUtils.class.getResourceAsStream("password.dat");
- byte[] b = new byte[1024];
- try {
- int len = is.read(b);
- password = new String(b,0,len);
- } catch (IOException e) {
- e.printStackTrace();
- }
- return new PasswordAuthentication(FROM, password);
- }
- });
- return session;
- }
- }
package org.study.accountactivate.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message.RecipientType;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.study.accountactivate.domail.User;
public class EmailUtils {
private static final String FROM = "[email protected]";
/**
* 註冊成功後,向用戶發送帳戶激活鏈接的郵件
* @param user 未激活的用戶
*/
public static void sendAccountActivateEmail(User user) {
Session session = getSession();
MimeMessage message = new MimeMessage(session);
try {
message.setSubject("帳戶激活郵件");
message.setSentDate(new Date());
message.setFrom(new InternetAddress(FROM));
message.setRecipient(RecipientType.TO, new InternetAddress(user.getEmail()));
message.setContent("<a href='" + GenerateLinkUtils.generateActivateLink(user)+"'>點擊激活帳戶</a>","text/html;charset=utf-8");
// 發送郵件
Transport.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 發送重設密碼鏈接的郵件
*/
public static void sendResetPasswordEmail(User user) {
Session session = getSession();
MimeMessage message = new MimeMessage(session);
try {
message.setSubject("找回您的帳戶與密碼");
message.setSentDate(new Date());
message.setFrom(new InternetAddress(FROM));
message.setRecipient(RecipientType.TO, new InternetAddress(user.getEmail()));
message.setContent("要使用新的密碼, 請使用以下鏈接啓用密碼:<br/><a href='" + GenerateLinkUtils.generateResetPwdLink(user) +"'>點擊重新設置密碼</a>","text/html;charset=utf-8");
// 發送郵件
Transport.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Session getSession() {
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.smtp.host", "smtp.163.com");
props.setProperty("mail.smtp.port", "25");
props.setProperty("mail.smtp.auth", "true");
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
String password = null;
InputStream is = EmailUtils.class.getResourceAsStream("password.dat");
byte[] b = new byte[1024];
try {
int len = is.read(b);
password = new String(b,0,len);
} catch (IOException e) {
e.printStackTrace();
}
return new PasswordAuthentication(FROM, password);
}
});
return session;
}
}
6、生成帳戶激活、密碼重設鏈接的工具類(GenerateLinkUtils)
- package org.study.accountactivate.util;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- import javax.servlet.ServletRequest;
- import org.study.accountactivate.domail.User;
- /**
- * 生成帳戶激活、重新設置密碼的鏈接
- */
- public class GenerateLinkUtils {
- private static final String CHECK_CODE = "checkCode";
- /**
- * 生成帳戶激活鏈接
- */
- public static String generateActivateLink(User user) {
- return "http://localhost:8080/AccountActivate/activateAccount?id="
- + user.getId() + "&" + CHECK_CODE + "=" + generateCheckcode(user);
- }
- /**
- * 生成重設密碼的鏈接
- */
- public static String generateResetPwdLink(User user) {
- return "http://localhost:8080/AccountActivate/resetPasswordUI?userName="
- + user.getUserName() + "&" + CHECK_CODE + "=" + generateCheckcode(user);
- }
- /**
- * 生成驗證帳戶的MD5校驗碼
- * @param user 要激活的帳戶
- * @return 將用戶名和密碼組合後,通過md5加密後的16進制格式的字符串
- */
- public static String generateCheckcode(User user) {
- String userName = user.getUserName();
- String randomCode = user.getRandomCode();
- return md5(userName + ":" + randomCode);
- }
- /**
- * 驗證校驗碼是否和註冊時發送的驗證碼一致
- * @param user 要激活的帳戶
- * @param checkcode 註冊時發送的校驗碼
- * @return 如果一致返回true,否則返回false
- */
- public static boolean verifyCheckcode(User user,ServletRequest request) {
- String checkCode = request.getParameter(CHECK_CODE);
- return generateCheckcode(user).equals(checkCode);
- }
- private static String md5(String string) {
- MessageDigest md = null;
- try {
- md = MessageDigest.getInstance("md5");
- md.update(string.getBytes());
- byte[] md5Bytes = md.digest();
- return bytes2Hex(md5Bytes);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return null;
- }
- private static String bytes2Hex(byte[] byteArray)
- {
- StringBuffer strBuf = new StringBuffer();
- for (int i = 0; i < byteArray.length; i++)
- {
- if(byteArray[i] >= 0 && byteArray[i] < 16)
- {
- strBuf.append("0");
- }
- strBuf.append(Integer.toHexString(byteArray[i] & 0xFF));
- }
- return strBuf.toString();
- }
- }
package org.study.accountactivate.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.servlet.ServletRequest;
import org.study.accountactivate.domail.User;
/**
* 生成帳戶激活、重新設置密碼的鏈接
*/
public class GenerateLinkUtils {
private static final String CHECK_CODE = "checkCode";
/**
* 生成帳戶激活鏈接
*/
public static String generateActivateLink(User user) {
return "http://localhost:8080/AccountActivate/activateAccount?id="
+ user.getId() + "&" + CHECK_CODE + "=" + generateCheckcode(user);
}
/**
* 生成重設密碼的鏈接
*/
public static String generateResetPwdLink(User user) {
return "http://localhost:8080/AccountActivate/resetPasswordUI?userName="
+ user.getUserName() + "&" + CHECK_CODE + "=" + generateCheckcode(user);
}
/**
* 生成驗證帳戶的MD5校驗碼
* @param user 要激活的帳戶
* @return 將用戶名和密碼組合後,通過md5加密後的16進制格式的字符串
*/
public static String generateCheckcode(User user) {
String userName = user.getUserName();
String randomCode = user.getRandomCode();
return md5(userName + ":" + randomCode);
}
/**
* 驗證校驗碼是否和註冊時發送的驗證碼一致
* @param user 要激活的帳戶
* @param checkcode 註冊時發送的校驗碼
* @return 如果一致返回true,否則返回false
*/
public static boolean verifyCheckcode(User user,ServletRequest request) {
String checkCode = request.getParameter(CHECK_CODE);
return generateCheckcode(user).equals(checkCode);
}
private static String md5(String string) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("md5");
md.update(string.getBytes());
byte[] md5Bytes = md.digest();
return bytes2Hex(md5Bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
private static String bytes2Hex(byte[] byteArray)
{
StringBuffer strBuf = new StringBuffer();
for (int i = 0; i < byteArray.length; i++)
{
if(byteArray[i] >= 0 && byteArray[i] < 16)
{
strBuf.append("0");
}
strBuf.append(Integer.toHexString(byteArray[i] & 0xFF));
}
return strBuf.toString();
}
}
7、實體類(User)
- package org.study.accountactivate.domail;
- public class User {
- // 編號
- private int id;
- // 用戶名
- private String userName;
- // 密碼
- private String password;
- private String email;
- // 是否激活
- private boolean activated;
- // 隨機碼(激活帳戶與生成重設密碼鏈接時使用)
- private String randomCode;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public boolean isActivated() {
- return activated;
- }
- public void setActivated(boolean activated) {
- this.activated = activated;
- }
- public String getRandomCode() {
- return randomCode;
- }
- public void setRandomCode(String randomCode) {
- this.randomCode = randomCode;
- }
- public String getEmail() {
- return email;
- }
- public void setEmail(String email) {
- this.email = email;
- }
- }
package org.study.accountactivate.domail;
public class User {
// 編號
private int id;
// 用戶名
private String userName;
// 密碼
private String password;
// email
private String email;
// 是否激活
private boolean activated;
// 隨機碼(激活帳戶與生成重設密碼鏈接時使用)
private String randomCode;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isActivated() {
return activated;
}
public void setActivated(boolean activated) {
this.activated = activated;
}
public String getRandomCode() {
return randomCode;
}
public void setRandomCode(String randomCode) {
this.randomCode = randomCode;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
功能實現步驟(忘記密碼):
1、登錄頁面
- <form action="${pageContext.request.contextPath}/login" method="post">
- <span class="error" style="display: block;">${errors.loginError}</span>
- 用戶名:<input type="text" name="userName" value="${param.userName}"><span class="error">${errors.userName}</span><br/>
- 密碼:<input type="password" name="password"><span class="error">${errors.password}</span><br/>
- <input type="submit" value="登錄">
- <a href="${pageContext.request.contextPath}/forgotPwdUI">忘記密碼?</a>
- <a href="${pageContext.request.contextPath}/registerUI">註冊</a>
- </form>
<form action="${pageContext.request.contextPath}/login" method="post">
<span class="error" style="display: block;">${errors.loginError}</span>
用戶名:<input type="text" name="userName" value="${param.userName}"><span class="error">${errors.userName}</span><br/>
密碼:<input type="password" name="password"><span class="error">${errors.password}</span><br/>
<input type="submit" value="登錄">
<a href="${pageContext.request.contextPath}/forgotPwdUI">忘記密碼?</a>
<a href="${pageContext.request.contextPath}/registerUI">註冊</a>
</form>
2、發送重設密碼申請的頁面
- <form action="${pageContext.request.contextPath}/forgotPwd" method="post">
- <span style="color: red">${requestScope.sendMailMsg}</span>
- 用戶名/郵箱:<input type="text" name="userNameOrEmail" /><span style="color: red">${requestScope.errorMsg}</span><br/>
- <input type="submit" value="提交" /><a href=""></a>
- </form>
<form action="${pageContext.request.contextPath}/forgotPwd" method="post">
<span style="color: red">${requestScope.sendMailMsg}</span>
用戶名/郵箱:<input type="text" name="userNameOrEmail" /><span style="color: red">${requestScope.errorMsg}</span><br/>
<input type="submit" value="提交" /><a href=""></a>
</form>
3、處理“發送重設密碼鏈接“請求的Servlet(ForgotPwdServlet)
- package org.study.accountactivate.web.servlet;
- import java.io.IOException;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.study.accountactivate.dao.UserDao;
- import org.study.accountactivate.dao.impl.UserDaoImpl;
- import org.study.accountactivate.domail.User;
- import org.study.accountactivate.util.EmailUtils;
- /**
- * 發送重設密碼申請的鏈接
- */
- public class ForgotPwdServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String userNameOrEmail = request.getParameter("userNameOrEmail");
- UserDao userDao = UserDaoImpl.getInstance();
- User user = userDao.findUserByNameOrEmail(userNameOrEmail);
- if (user == null) {
- request.setAttribute("errorMsg", userNameOrEmail + ",不存在!");
- request.getRequestDispatcher("/forgotPwdUI").forward(request, response);
- return;
- }
- // 發送重新設置密碼的鏈接
- EmailUtils.sendResetPasswordEmail(user);
- request.setAttribute("sendMailMsg", "您的申請已提交成功,請查看您的"+user.getEmail()+"郵箱。");
- request.getRequestDispatcher("/WEB-INF/pages/forgotPwdSuccess.jsp").forward(request, response);
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- doGet(request, response);
- }
- }
package org.study.accountactivate.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.study.accountactivate.dao.UserDao;
import org.study.accountactivate.dao.impl.UserDaoImpl;
import org.study.accountactivate.domail.User;
import org.study.accountactivate.util.EmailUtils;
/**
* 發送重設密碼申請的鏈接
*/
public class ForgotPwdServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userNameOrEmail = request.getParameter("userNameOrEmail");
UserDao userDao = UserDaoImpl.getInstance();
User user = userDao.findUserByNameOrEmail(userNameOrEmail);
if (user == null) {
request.setAttribute("errorMsg", userNameOrEmail + ",不存在!");
request.getRequestDispatcher("/forgotPwdUI").forward(request, response);
return;
}
// 發送重新設置密碼的鏈接
EmailUtils.sendResetPasswordEmail(user);
request.setAttribute("sendMailMsg", "您的申請已提交成功,請查看您的"+user.getEmail()+"郵箱。");
request.getRequestDispatcher("/WEB-INF/pages/forgotPwdSuccess.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
4、重新設置密碼的頁面
- <form action="${pageContext.request.contextPath}/resetPassword" method="post">
- <span class="error" style="display: block;">${errors.passwordError}</span>
- 用戶名:<input type="text" name="userName" value="${userName}" readonly="readonly"/><br/>
- 新密碼:<input type="password" name="newPassword" /><span class="error">${errors.newPassword }</span><br/>
- 確認新密碼:<input type="password" name="newPassword2"/><span class="error">${errors.newPassword2 }</span><br/>
- <input type="submit" value="修改" />
- </form>
<form action="${pageContext.request.contextPath}/resetPassword" method="post">
<span class="error" style="display: block;">${errors.passwordError}</span>
用戶名:<input type="text" name="userName" value="${userName}" readonly="readonly"/><br/>
新密碼:<input type="password" name="newPassword" /><span class="error">${errors.newPassword }</span><br/>
確認新密碼:<input type="password" name="newPassword2"/><span class="error">${errors.newPassword2 }</span><br/>
<input type="submit" value="修改" />
</form>
5、處理重新設置密碼請求的Servlet(ResetPasswordServlet)
- package org.study.accountactivate.web.servlet;
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.Map;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.study.accountactivate.dao.UserDao;
- import org.study.accountactivate.dao.impl.UserDaoImpl;
- import org.study.accountactivate.domail.User;
- /**
- * 重新設置密碼
- */
- public class ResetPasswordServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String userName = request.getParameter("userName");
- String newPassword = request.getParameter("newPassword");
- String newPassword2 = request.getParameter("newPassword2");
- Map<String,String> errors = new HashMap<String, String>();
- if (newPassword == null || "".equals(newPassword)) {
- errors.put("newPassword", "新密碼不能爲空!");
- }
- if (newPassword2 == null || "".equals(newPassword2)) {
- errors.put("newPassword2", "確認新密碼不能爲空!");
- }
- if (!newPassword.equals(newPassword2)) {
- errors.put("passwordError", "兩次輸入的密碼不一致!");
- }
- if (!errors.isEmpty()) {
- request.setAttribute("errors", errors);
- request.getRequestDispatcher("/resetPasswordUI?userName=" + userName).forward(request, response);
- return;
- }
- UserDao userDao = UserDaoImpl.getInstance();
- User user = userDao.findUserByName(userName);
- user.setPassword(newPassword);
- request.getRequestDispatcher("/WEB-INF/pages/resetPasswordSuccess.jsp").forward(request, response);
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- doGet(request, response);
- }
- }
package org.study.accountactivate.web.servlet;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.study.accountactivate.dao.UserDao;
import org.study.accountactivate.dao.impl.UserDaoImpl;
import org.study.accountactivate.domail.User;
/**
* 重新設置密碼
*/
public class ResetPasswordServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = request.getParameter("userName");
String newPassword = request.getParameter("newPassword");
String newPassword2 = request.getParameter("newPassword2");
Map<String,String> errors = new HashMap<String, String>();
if (newPassword == null || "".equals(newPassword)) {
errors.put("newPassword", "新密碼不能爲空!");
}
if (newPassword2 == null || "".equals(newPassword2)) {
errors.put("newPassword2", "確認新密碼不能爲空!");
}
if (!newPassword.equals(newPassword2)) {
errors.put("passwordError", "兩次輸入的密碼不一致!");
}
if (!errors.isEmpty()) {
request.setAttribute("errors", errors);
request.getRequestDispatcher("/resetPasswordUI?userName=" + userName).forward(request, response);
return;
}
UserDao userDao = UserDaoImpl.getInstance();
User user = userDao.findUserByName(userName);
user.setPassword(newPassword);
request.getRequestDispatcher("/WEB-INF/pages/resetPasswordSuccess.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
帳戶激活操作流程:
1)、註冊頁面
2)、註冊成功頁面
3)、帳戶未激活,登錄後的界面
4)、前往郵箱中激活帳戶
5)、激活成功
6)、帳戶已激活,登錄後的界面
忘記密碼操作流程:
1)、登錄頁面(點擊“忘記密碼”鏈接,進入重設密碼頁面)
2、重設密碼申請頁面(輸入用戶名或郵箱,點擊“提交”按鈕)
3、重設密碼申請成功頁面
4、郵箱中重設密碼的鏈接
5、重新設置密碼頁面
6、密碼重新設置成功頁面