Java實現(xiàn)注冊郵箱激活賬戶實例代碼
在網(wǎng)站注冊時一般都會要驗證注冊用戶身份的合法性,通常的做法是提供手機(jī)號驗證或者郵箱驗證。
手機(jī)驗證:填寫手機(jī)號碼,點擊發(fā)送驗證碼,接收后填寫驗證碼比對,無誤后注冊成功。
郵箱驗證:注冊時填寫郵箱賬號,點擊注冊,網(wǎng)站郵箱會給該郵箱發(fā)送一封激活郵件,用戶點擊后激活該賬號。
這里通過實例來介紹一下郵箱驗證的實現(xiàn)過程,例子可以運行,暫時沒有發(fā)現(xiàn)什么問題,不過也可能有不安全的地方,歡迎大家指正。
實現(xiàn)思路
注冊時填寫郵箱,點擊注冊時網(wǎng)站系統(tǒng)郵箱發(fā)送激活驗證鏈接到此郵箱,用戶來激活賬戶
點擊注冊,系統(tǒng)郵箱會發(fā)送一封激活郵件到你填寫的郵箱賬號中
在沒有進(jìn)行激活操作前,設(shè)定某個字段狀態(tài)是0,表示此賬號未激活,不可以使用或者某些功能受限
激活操作之后,將activated字段更新為1,這樣就完成了激活操作
那么這里還有一個codeUrl字段,他的作用是存入一個唯一標(biāo)識的隨機(jī)碼,這個隨機(jī)碼由用戶名和UUID唯一標(biāo)識的隨機(jī)數(shù)組成,這樣做的目的是防止用戶使用不存在的郵箱又修改鏈接中的參數(shù)來激活賬戶,將鏈接中的隨機(jī)碼和數(shù)據(jù)庫中的比對,來達(dá)到相對安全的激活。
下面是具體的代碼
首先是注冊的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); //剛注冊默認(rèn)是沒有激活狀態(tài) String SQL = "insert into tb_user(username,password,email,activated,codeUrl) value (?,?,?,?,?) "; MyJDBC.insert(SQL, false, username,password,email,0,codeUrl);//注冊信息插入數(shù)據(jù)庫 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(); } // 注冊成功后,發(fā)送帳戶激活鏈接 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(); } //驗證無誤,狀態(tài)更改為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); } } }
發(fā)送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 = "要發(fā)送郵件的郵箱,這個例子是163郵箱"; public static void sendAccountActivateEmail(User user) { Session session = getSession(); MimeMessage message = new MimeMessage(session); try { message.setSubject("這是一封激活賬號的郵件,復(fù)制鏈接到地址欄來激活他"); 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郵箱,需要進(jìn)行郵箱客戶端的授權(quán),授權(quán)之后,網(wǎng)易郵箱會發(fā)來一份客戶端授權(quán)碼作為替代郵箱密碼,代碼里填寫的密碼其實是授權(quán)碼,配置好郵箱最好發(fā)一份郵件測試一下,有時程序出問題很可能是郵箱客戶端根本發(fā)不了郵件
加密賬戶激活鏈接生成的工具類
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唯一標(biāo)識符,為安全把他們加密發(fā)送 * @param user * @return */ public static String generateCheckcode(User user) { String userName = user.getUsername(); String randomCode = user.getCodeUrl(); return md5(userName + ":" + randomCode); } /** * 接收回來的校驗碼和發(fā)送出去的是不是同一份 * @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(); } }
還有一個操作數(shù)據(jù)庫的封裝類,MyJDBC,前面博客有寫,代碼挺長,就不貼了,這是鏈接:
http://www.dbjr.com.cn/article/70107.htm
http://www.dbjr.com.cn/article/88647.htm
實體類User
package org.amuxia.emailtest.pojo; public class User { private int id; private String username; private String password; private String email; private boolean activated;//賬號狀態(tài) private String codeUrl;//激活鏈接中的隨機(jī)碼 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>
用到的包?
郵箱驗證的大概功能就完成了,但是還有很多不足之處,貌似應(yīng)該設(shè)置一個過期時間。等等。。。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
將ResultSet中得到的一行或多行結(jié)果集封裝成對象的實例
這篇文章主要介紹了將ResultSet中得到的一行或多行結(jié)果集封裝成對象的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05在Spring Boot中如何使用數(shù)據(jù)緩存
本篇文章主要介紹了在Spring Boot中如何使用數(shù)據(jù)緩存,具有一定的參考價值,有興趣的可以了解一下。2017-04-04SpringBoot+WebMagic+MyBaties實現(xiàn)爬蟲和數(shù)據(jù)入庫的示例
WebMagic是一個開源爬蟲框架,本項目通過在SpringBoot項目中使用WebMagic去抓取數(shù)據(jù),最后使用MyBatis將數(shù)據(jù)入庫。具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10Elasticsearch索引庫和文檔的相關(guān)操作詳細(xì)指南
這篇文章主要給大家介紹了關(guān)于Elasticsearch索引庫和文檔的相關(guān)操作的相關(guān)資料,Elasticsearch是用Java開發(fā)并且是當(dāng)前最流行的開源的企業(yè)級搜索引擎,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11MybatisPlus中插入數(shù)據(jù)后獲取該對象主鍵值的實現(xiàn)
這篇文章主要介紹了MybatisPlus中插入數(shù)據(jù)后獲取該對象主鍵值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09關(guān)于JDK+Tomcat+eclipse+MyEclipse的配置方法,看這篇夠了
關(guān)于JDK+Tomcat+eclipse+MyEclipse的配置問題,很多朋友都搞不太明白,網(wǎng)上一搜配置方法多種哪種最精簡呢,今天小編給大家分享一篇文章幫助大家快速掌握J(rèn)DK Tomcat eclipse MyEclipse配置技巧,需要的朋友參考下吧2021-06-06Springboot2.x+ShardingSphere實現(xiàn)分庫分表的示例代碼
這篇文章主要介紹了Springboot2.x+ShardingSphere實現(xiàn)分庫分表的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10spring cloud 之 Feign 使用HTTP請求遠(yuǎn)程服務(wù)的實現(xiàn)方法
下面小編就為大家?guī)硪黄猻pring cloud 之 Feign 使用HTTP請求遠(yuǎn)程服務(wù)的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06