Java實現郵箱啟用賬戶例項
阿新 • • 發佈:2019-01-28
在網站註冊時一般都會要驗證註冊使用者身份的合法性,通常的做法是提供手機號驗證或者郵箱驗證。
手機驗證:填寫手機號碼,點擊發送驗證碼,接收後填寫驗證碼比對,無誤後註冊成功。
郵箱驗證:註冊時填寫郵箱賬號,點選註冊,網站郵箱會給該郵箱傳送一封啟用郵件,使用者點選後啟用該賬號。
這裡通過例項來介紹一下郵箱驗證的實現過程,例子可以執行,暫時沒有發現什麼問題,不過也可能有不安全的地方,歡迎大家指正。
實現思路
註冊時填寫郵箱,點選註冊時網站系統郵箱傳送啟用驗證連結到此郵箱,使用者來啟用賬戶
點選註冊,系統郵箱會發送一封啟用郵件到你填寫的郵箱賬號中
在沒有進行啟用操作前,設定某個欄位狀態是0,表示此賬號未啟用,不可以使用或者某些功能受限
啟用操作之後,將activated欄位更新為1,這樣就完成了啟用操作
那麼這裡還有一個codeUrl欄位,他的作用是存入一個唯一標識的隨機碼,這個隨機碼由使用者名稱和UUID唯一標識的隨機陣列成,這樣做的目的是防止使用者使用不存在的郵箱又修改連結中的引數來啟用賬戶,將連結中的隨機碼和資料庫中的比對,來達到相對安全的啟用。
下面是具體的程式碼
首先是註冊的servlet,這裡主要測試啟用賬號的功能,註冊程式碼有點low,不安全,將就看一下
package org.amuxia.emailtest.servlet; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; import java.util.UUID; 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 org.amuxia.emailtest.pojo.User; import org.amuxia.emailtest.utils.EmailUtils; import org.amuxia.emailtest.utils.MyJDBC; /** * @author amuxia * 2017年7月24日 */ @WebServlet("/RegistServlet") public class RegistServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); String email = request.getParameter("email"); String codeUrl = UUID.randomUUID().toString(); User user = new User(); user.setUsername(username); user.setPassword(password); user.setEmail(email); user.setActivated(false); //剛註冊預設是沒有啟用狀態 String SQL = "insert into tb_user(username,password,email,activated,codeUrl) value (?,?,?,?,?) "; MyJDBC.insert(SQL, false, username,password,email,0,codeUrl);//註冊資訊插入資料庫 String querySQL = "select * from tb_user where email=?"; ResultSet rs = MyJDBC.query(querySQL, email); try { if(rs.next()){ user.setId(rs.getInt(1)); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 註冊成功後,傳送帳戶啟用連結 request.getSession().setAttribute("user", user); EmailUtils.sendAccountActivateEmail(user); request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request,response); } }
啟用賬號的Servlet,也就是更新操作
package org.amuxia.emailtest.servlet; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; 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 org.amuxia.emailtest.pojo.User; import org.amuxia.emailtest.utils.GenerateLinkUtils; import org.amuxia.emailtest.utils.MyJDBC; /** * @author amuxia * 2017年7月24日 */ @WebServlet("/ActivateServlet") public class ActivateServlet extends HttpServlet{ private static final long serialVersionUID = 1L; @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String idValue = request.getParameter("id"); System.out.println(idValue); int id = -1; try { id = Integer.parseInt(idValue); } catch (NumberFormatException e) { e.printStackTrace(); } String SQL = "select * from tb_user where id=?"; ResultSet rs= MyJDBC.query(SQL, id); User user = new User(); try { if(rs.next()){ user.setId(rs.getInt(1)); user.setUsername(rs.getString(2)); user.setPassword(rs.getString(3)); user.setEmail(rs.getString(4)); user.setActivated(rs.getBoolean(5)); user.setCodeUrl(rs.getString(6)); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } //驗證無誤,狀態更改為1,即啟用 if(GenerateLinkUtils.verifyCheckcode(user, request)){ String updSQL = "update tb_user set activated =1 where id=?"; MyJDBC.execute(updSQL, id); user.setActivated(true); request.getSession().setAttribute("user", user); request.getRequestDispatcher("/WEB-INF/jsp/pass.jsp").forward(request, response); } } }
傳送Email的工具類
package org.amuxia.emailtest.utils;
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.amuxia.emailtest.pojo.User;
/**
* @author amuxia
* 2017年7月24日
*/
public class EmailUtils {
private static final String FROM = "要傳送郵件的郵箱,這個例子是163郵箱";
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 target='_BLANK' href=''>"+GenerateLinkUtils.generateActivateLink(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() {
return new PasswordAuthentication(FROM, "上面郵箱的密碼");
}
});
return session;
}
}
這裡需要注意一下,以上例子配置的是163郵箱,需要進行郵箱客戶端的授權,授權之後,網易郵箱會發來一份客戶端授權碼作為替代郵箱密碼,程式碼裡填寫的密碼其實是授權碼,配置好郵箱最好發一份郵件測試一下,有時程式出問題很可能是郵箱客戶端根本發不了郵件
加密賬戶啟用連結生成的工具類
package org.amuxia.emailtest.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.servlet.ServletRequest;
import org.amuxia.emailtest.pojo.User;
/**
* @author amuxia
* 2017年7月24日
*/
public class GenerateLinkUtils {
private static final String CHECK_CODE = "checkCode";
public static String generateActivateLink(User user) {
return "http://localhost/EmailDemo/ActivateServlet?id="
+ user.getId() + "&" + CHECK_CODE + "=" + generateCheckcode(user);
}
/**
* 生成校驗碼,使用者名稱+UUID唯一識別符號,為安全把他們加密傳送
* @param user
* @return
*/
public static String generateCheckcode(User user) {
String userName = user.getUsername();
String randomCode = user.getCodeUrl();
return md5(userName + ":" + randomCode);
}
/**
* 接收回來的校驗碼和傳送出去的是不是同一份
* @param user
* @param request
* @return
*/
public static boolean verifyCheckcode(User user,ServletRequest request) {
String checkCode = request.getParameter(CHECK_CODE);
System.out.println(generateCheckcode(user).equals(checkCode));
return true;
}
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();
System.out.println("md5這裡出錯了");
}
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();
}
}
還有一個操作資料庫的封裝類,MyJDBC,前面部落格有寫,程式碼挺長,就不貼了,這是連結:http://blog.csdn.net/weixin_36380516/article/details/72904214
實體類User
package org.amuxia.emailtest.pojo;
public class User {
private int id;
private String username;
private String password;
private String email;
private boolean activated;//賬號狀態
private String codeUrl;//啟用連結中的隨機碼
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isActivated() {
return activated;
}
public void setActivated(boolean activated) {
this.activated = activated;
}
public String getCodeUrl() {
return codeUrl;
}
public void setCodeUrl(String codeUrl) {
this.codeUrl = codeUrl;
}
public User() {
super();
}
}
註冊的jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>註冊</title>
</head>
<body>
<form action="/EmailDemo/RegistServlet" method="post">
使用者名稱:<input type="text" name="username"><br/>
密碼:<input type="password" name="password"><br/>
郵箱:<input type="text" name="email"><br/>
<input type="submit" value="註冊">
</form>
</body>
</html>
用到的包?
郵箱驗證的大概功能就完成了,但是還有很多不足之處,貌似應該設定一個過期時間。等等。。。