目录
一、简介
1.什么是邮箱验证
邮箱验证是一种验证用户提供的邮箱地址的有效性和真实性的过程。在用户进行注册、订阅或重置密码等操作时,邮箱验证通常是必需的。通过邮箱验证,系统会向用户提供的邮箱地址发送一封包含验证码或确认链接的邮件。用户需要登录到邮箱账户,查找并打开这封邮件,并按照邮件中的指示进行验证操作。这可以包括点击确认链接或输入验证码。如果用户成功完成验证,系统将确认该邮箱地址是有效的并与用户的账户相关联。邮箱验证的目的是确保用户提供的邮箱地址是真实存在的和可被访问的,以减少垃圾邮件、保护用户隐私和确保有效的通信。
2.邮箱验证的作用
1、网站的安全性增加,防止恶意注册。
2、作为用户丢失密码后的验证渠道。相比短信,邮箱不存在费用问题,但前提是用户填写的邮箱是正确的。
3、CRM(客户关系管理)数据收集。邮箱是一种相对于短信更便宜的营销渠道,发送不费成本,用户也不会极为反感。作为后续的客户维护渠道,邮箱是不可舍弃的资源。验证过的邮箱,很大程序上增加了用户打开的几率
二、邮箱验证(点击链接完成激活)
准备工作
准备两个邮箱账号,这里我使用的是QQ和网易。
导入jar包(mail.jar和activation.jar)
1.首先开启邮箱服务(QQ邮箱为例)
开启服务后会有一个授权码,发送邮件的时候会使用
2.生成激活用户的超链接
其中只需要修改写信人的账号和授权码
package com.school.utils;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
public class EmailUtils {
public static void sendEmail(String email,String authCode) throws MessagingException {
// 创建Properties 类用于记录邮箱的一些属性
Properties props = new Properties();
// 表示SMTP发送邮件,必须进行身份验证
props.put("mail.smtp.auth", "true");
//此处填写SMTP服务器
props.put("mail.smtp.host", "smtp.qq.com");
//端口号,QQ邮箱端口587
props.put("mail.smtp.port", "587");
// 此处填写,写信人的账号
props.put("mail.user", "2160625419@qq.com");
// 此处填写授权码
props.put("mail.password", "uzolknqwokdybiia");
// 构建授权信息,用于进行SMTP进行身份验证
Authenticator authenticator = new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
// 用户名、密码,都不用改直接copy
String userName = props.getProperty("mail.user");
String password = props.getProperty("mail.password");
return new PasswordAuthentication(userName, password);
}
};
// 使用环境属性和授权信息,创建邮件会话
Session mailSession = Session.getInstance(props, authenticator);
// 创建邮件消息
MimeMessage message = new MimeMessage(mailSession);
// 设置发件人,
InternetAddress form = new InternetAddress(props.getProperty("mail.user"));
message.setFrom(form);
// 设置收件人的邮箱
InternetAddress to = new InternetAddress(email);
message.setRecipient(Message.RecipientType.TO, to);
// 设置邮件标题
message.setSubject("验证码信息");
// 设置邮件的内容体
message.setContent("验证码:"+authCode, "text/html;charset=UTF-8");
// 最后当然就是发送邮件啦
Transport.send(message);
}
}
3.注册时发送链接到指定邮箱
Controller层
用于激活用户的Servlet
package com.school.web.controller;
import com.school.service.TeacherService;
import com.school.service.impl.TeacherServiceimpl;
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;
@WebServlet("/EmailActivate")
public class EmailActivate extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String activatecode = req.getParameter("activatecode");
System.out.println(activatecode);
if ("".equals(activatecode) || activatecode!=null){
TeacherService teacherService = new TeacherServiceimpl();
boolean flag = teacherService.updateState(activatecode);
if (flag){
req.setAttribute("stateinfor","激活成功");
req.getRequestDispatcher("/stateinfor.jsp").forward(req,resp);
}else {
req.setAttribute("stateinfor","激活失败");
req.getRequestDispatcher("/stateinfor.jsp").forward(req,resp);
}
}else {
req.setAttribute("stateinfor","激活码错误");
req.getRequestDispatcher("/stateinfor.jsp").forward(req,resp);
}
}
}
用于用户注册的Servlet
//注册
if ("register_teacher".equals(Action)){
//接收并封装数据
Teacher teacher = new Teacher();
try {
BeanUtils.populate(teacher,req.getParameterMap());
//使用UUID生成激活码并发送到邮箱
teacher.setActivatecode(UUID.randomUUID().toString());
teacher.setState("N");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//调用Service层的方法来完成业务
Map<String, String> error = ValidateDemo.validate(teacher);
if (error.isEmpty()){
TeacherService teacherServiceimpl = new TeacherServiceimpl();
int flag = teacherServiceimpl.register(teacher);
if (flag==1){
//注意链接的地址
String authCode = "<a href=http://localhost:8080/schoolpro01/EmailActivate?activatecode="+teacher.getActivatecode()+">点击激活</a>";
try {
EmailUtils.sendEmail(teacher.getEmail(),authCode);
req.getRequestDispatcher("/pages/registersuccess.jsp").forward(req,resp);
} catch (MessagingException e) {
e.printStackTrace();
}
}
if (flag==0){
req.getRequestDispatcher("/pages/registerfail.jsp").forward(req,resp);
}
if (flag==2){
req.setAttribute("registererror","该用户已存在");
req.getRequestDispatcher("/register_teacher.jsp").forward(req,resp);
}
}else {
req.setAttribute("error",error);
req.getRequestDispatcher("/register_teacher.jsp").forward(req,resp);
}
}
Service层
/**
* 修改用户状态
*
*/
@Override
public boolean updateState(String activatecode) {
TeacherDao teacherDao = new TeacherDaoimpl();
int flag = teacherDao.updateTeacherState(activatecode);
if (flag>0){
return true;
}
return false;
}
Dao层
/**
* 修改用户状态码
*
*/
@Override
public int updateTeacherState(String activatecode) {
Connection conn = null;
PreparedStatement ps = null;
String sql = null;
int i = 0;
try {
conn = DBUtils.getConnection();
sql = "update teacher set state=? where activatecode=?";
ps = conn.prepareStatement(sql);
ps.setString(1,"Y");
ps.setString(2,activatecode);
i = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
//关闭数据库连接
DBUtils.closeDB(conn,ps,null);
return i;
}
4.实现登录判断用户是否激活
Controller层
//登录
if ("login".equals(Action)) {
//验证码合法性
String infor = (String) req.getSession().getAttribute("infor");
String validateinput = req.getParameter("validateinput");
if(validateinput!=null&&infor.equalsIgnoreCase(validateinput)){
Teacher teacher = new Teacher();
try {
//封装数据
BeanUtils.populate(teacher, req.getParameterMap());
Map<String, String> error = ValidateDemo.validatelogin(teacher);
if (error.isEmpty()) {
TeacherService teacherService = new TeacherServiceimpl();
//验证用户是否激活
boolean b = teacherService.showState(teacher.getName());
if (b){
boolean flag = teacherService.login(teacher.getName(), teacher.getPassword());
if (flag) {
//登录成功
req.getSession().setAttribute("name", teacher.getName());
req.getRequestDispatcher("/pages/admin_main.jsp").forward(req, resp);
} else {
//登录失败
req.setAttribute("fail", "用户名或密码不正确!");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}else {
req.setAttribute("er","用户未激活");
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}
} else {
req.setAttribute("error", error);
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}else {
req.setAttribute("validateinfor","验证码错误");
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}
}
Service层
/**
* 查询状态用户(Y是激活,N是没有激活)
*/
@Override
public boolean showState(String name) {
TeacherDao teacherDao = new TeacherDaoimpl();
String state = teacherDao.findTeacherStateByName(name);
if ("Y".equals(state)){
return true;
}
return false;
}
Dao层
/**
* 根据用户名查询激活状态
*/
@Override
public String findTeacherStateByName(String name) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = null;
String state = null;
try {
conn = DBUtils.getConnection();
sql = "select state from teacher where name=?";
ps = conn.prepareStatement(sql);
ps.setString(1,name);
rs = ps.executeQuery();
while (rs.next()){
state = rs.getString("state");
}
} catch (SQLException e) {
e.printStackTrace();
}
DBUtils.closeDB(conn,ps,rs);
return state;
}
5.运行效果
注册用户
前往登录
点击登录后发现用户没有激活
激活用户
登录邮箱找到发送的邮件
点击链接出现激活成功后再去登录
激活后登录
点击登录后成功登录