Java實(shí)現(xiàn)注冊(cè)郵箱激活賬戶實(shí)例代碼
在網(wǎng)站注冊(cè)時(shí)一般都會(huì)要驗(yàn)證注冊(cè)用戶身份的合法性,通常的做法是提供手機(jī)號(hào)驗(yàn)證或者郵箱驗(yàn)證。
手機(jī)驗(yàn)證:填寫(xiě)手機(jī)號(hào)碼,點(diǎn)擊發(fā)送驗(yàn)證碼,接收后填寫(xiě)驗(yàn)證碼比對(duì),無(wú)誤后注冊(cè)成功。
郵箱驗(yàn)證:注冊(cè)時(shí)填寫(xiě)郵箱賬號(hào),點(diǎn)擊注冊(cè),網(wǎng)站郵箱會(huì)給該郵箱發(fā)送一封激活郵件,用戶點(diǎn)擊后激活該賬號(hào)。
這里通過(guò)實(shí)例來(lái)介紹一下郵箱驗(yàn)證的實(shí)現(xiàn)過(guò)程,例子可以運(yùn)行,暫時(shí)沒(méi)有發(fā)現(xiàn)什么問(wèn)題,不過(guò)也可能有不安全的地方,歡迎大家指正。
實(shí)現(xiàn)思路
注冊(cè)時(shí)填寫(xiě)郵箱,點(diǎn)擊注冊(cè)時(shí)網(wǎng)站系統(tǒng)郵箱發(fā)送激活驗(yàn)證鏈接到此郵箱,用戶來(lái)激活賬戶

點(diǎn)擊注冊(cè),系統(tǒng)郵箱會(huì)發(fā)送一封激活郵件到你填寫(xiě)的郵箱賬號(hào)中

在沒(méi)有進(jìn)行激活操作前,設(shè)定某個(gè)字段狀態(tài)是0,表示此賬號(hào)未激活,不可以使用或者某些功能受限

激活操作之后,將activated字段更新為1,這樣就完成了激活操作
那么這里還有一個(gè)codeUrl字段,他的作用是存入一個(gè)唯一標(biāo)識(shí)的隨機(jī)碼,這個(gè)隨機(jī)碼由用戶名和UUID唯一標(biāo)識(shí)的隨機(jī)數(shù)組成,這樣做的目的是防止用戶使用不存在的郵箱又修改鏈接中的參數(shù)來(lái)激活賬戶,將鏈接中的隨機(jī)碼和數(shù)據(jù)庫(kù)中的比對(duì),來(lái)達(dá)到相對(duì)安全的激活。
下面是具體的代碼
首先是注冊(cè)的servlet,這里主要測(cè)試激活賬號(hào)的功能,注冊(cè)代碼有點(diǎn)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); //剛注冊(cè)默認(rèn)是沒(méi)有激活狀態(tài)
String SQL = "insert into tb_user(username,password,email,activated,codeUrl) value (?,?,?,?,?) ";
MyJDBC.insert(SQL, false, username,password,email,0,codeUrl);//注冊(cè)信息插入數(shù)據(jù)庫(kù)
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();
}
// 注冊(cè)成功后,發(fā)送帳戶激活鏈接
request.getSession().setAttribute("user", user);
EmailUtils.sendAccountActivateEmail(user);
request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request,response);
}
}
激活賬號(hào)的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();
}
//驗(yàn)證無(wú)誤,狀態(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ā)送郵件的郵箱,這個(gè)例子是163郵箱";
public static void sendAccountActivateEmail(User user) {
Session session = getSession();
MimeMessage message = new MimeMessage(session);
try {
message.setSubject("這是一封激活賬號(hào)的郵件,復(fù)制鏈接到地址欄來(lái)激活他");
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)易郵箱會(huì)發(fā)來(lái)一份客戶端授權(quán)碼作為替代郵箱密碼,代碼里填寫(xiě)的密碼其實(shí)是授權(quán)碼,配置好郵箱最好發(fā)一份郵件測(cè)試一下,有時(shí)程序出問(wèn)題很可能是郵箱客戶端根本發(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);
}
/**
* 生成校驗(yàn)碼,用戶名+UUID唯一標(biāo)識(shí)符,為安全把他們加密發(fā)送
* @param user
* @return
*/
public static String generateCheckcode(User user) {
String userName = user.getUsername();
String randomCode = user.getCodeUrl();
return md5(userName + ":" + randomCode);
}
/**
* 接收回來(lái)的校驗(yàn)碼和發(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這里出錯(cuò)了");
}
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();
}
}
還有一個(gè)操作數(shù)據(jù)庫(kù)的封裝類,MyJDBC,前面博客有寫(xiě),代碼挺長(zhǎng),就不貼了,這是鏈接:
http://chabaoo.cn/article/70107.htm
http://chabaoo.cn/article/88647.htm
實(shí)體類User
package org.amuxia.emailtest.pojo;
public class User {
private int id;
private String username;
private String password;
private String email;
private boolean activated;//賬號(hào)狀態(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();
}
}
注冊(cè)的jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>注冊(cè)</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="注冊(cè)"> </form> </body> </html>
用到的包?

郵箱驗(yàn)證的大概功能就完成了,但是還有很多不足之處,貌似應(yīng)該設(shè)置一個(gè)過(guò)期時(shí)間。等等。。。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
將ResultSet中得到的一行或多行結(jié)果集封裝成對(duì)象的實(shí)例
這篇文章主要介紹了將ResultSet中得到的一行或多行結(jié)果集封裝成對(duì)象的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
在Spring Boot中如何使用數(shù)據(jù)緩存
本篇文章主要介紹了在Spring Boot中如何使用數(shù)據(jù)緩存,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-04-04
SpringBoot+WebMagic+MyBaties實(shí)現(xiàn)爬蟲(chóng)和數(shù)據(jù)入庫(kù)的示例
WebMagic是一個(gè)開(kāi)源爬蟲(chóng)框架,本項(xiàng)目通過(guò)在SpringBoot項(xiàng)目中使用WebMagic去抓取數(shù)據(jù),最后使用MyBatis將數(shù)據(jù)入庫(kù)。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
Elasticsearch索引庫(kù)和文檔的相關(guān)操作詳細(xì)指南
這篇文章主要給大家介紹了關(guān)于Elasticsearch索引庫(kù)和文檔的相關(guān)操作的相關(guān)資料,Elasticsearch是用Java開(kāi)發(fā)并且是當(dāng)前最流行的開(kāi)源的企業(yè)級(jí)搜索引擎,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
MybatisPlus中插入數(shù)據(jù)后獲取該對(duì)象主鍵值的實(shí)現(xiàn)
這篇文章主要介紹了MybatisPlus中插入數(shù)據(jù)后獲取該對(duì)象主鍵值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
關(guān)于JDK+Tomcat+eclipse+MyEclipse的配置方法,看這篇夠了
關(guān)于JDK+Tomcat+eclipse+MyEclipse的配置問(wèn)題,很多朋友都搞不太明白,網(wǎng)上一搜配置方法多種哪種最精簡(jiǎn)呢,今天小編給大家分享一篇文章幫助大家快速掌握J(rèn)DK Tomcat eclipse MyEclipse配置技巧,需要的朋友參考下吧2021-06-06
Springboot2.x+ShardingSphere實(shí)現(xiàn)分庫(kù)分表的示例代碼
這篇文章主要介紹了Springboot2.x+ShardingSphere實(shí)現(xiàn)分庫(kù)分表的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
spring cloud 之 Feign 使用HTTP請(qǐng)求遠(yuǎn)程服務(wù)的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇spring cloud 之 Feign 使用HTTP請(qǐng)求遠(yuǎn)程服務(wù)的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06

