一、帐户激活

      在很多时候,在某些网站注册一个用户之后,网站会给这个用户注册时填写的email地址发送一封帐户激活邮件,这封邮件的内容就是一个激活帐户的链接和一段简短的文字描述,如果用户没有去邮箱将帐户激活,可能在使用网站的某些功能时就会受到限制,比如不能发贴、下载资料、评论等限制。这么做的原因应该是为了保证帐户的安全性和邮箱的有效性,以后网站如果有什么活动、资讯或系统安全通知等,可以在第一时间通知到用户。比如我在奇艺视频网站注册一个帐号之后,它就会往我注册时填写的邮箱中发一封帐户激活的邮件,邮件中有一个激活的链接,点击它就可以将你的帐户激活。如下图所示:

这个功能是怎么做到的呢,其实实现也是很简单的,说白了就是一个Update操作。
实现思路:当一个用户注册成功之后,系统向用户注册时提供的email地址发送一封邮件,邮件的内容是一个激活帐户的链接和一段简短的文字描述,这个链接的功能就是将这个帐户的状态修改成激活状态。这个功能的重点在于如何生成这个激活帐户的链接。直接可以联想到的方法就是建一个Servlet,Servlet接收一个用户名参数,Servlet拿到用户名参数之后,到数据库把这条记录load出来,做一次update操作即可。但是这样做会有风险,比如有人想在你的网站上搞破坏,注册时他填的email地址就是乱填的,这个Email地址可能根本就收不到邮件(但符合email格式),注册完成之后,然后在浏览器地址栏输入网站之前发送的帐户激活链接,并加上新注册的用户名参数,这样一来就跳过了去邮箱激活的步聚,时间久了,库中可能会留下许多无效的email地址和帐户。为了避免这个问题,解决方案是在用户注册成功之后,在发送激活帐户的链接中加一个随机码,这个随机码是将用户名和一个随机数用md5加密后的一串16进制字符串,每次用户在激活帐户的时候,都验证这个随机码是否和注册时发送的一致,这样就可以避免人为的修改激活链接达到帐户激活的功能。
二、忘记密码

      当你在某网站注册一个帐户之后,发现这个帐户很久没用了,密码也忘记了,如果还记得之前注册时填写的Email,那就可以向你的email中发一个重设密码的链接,就可以重新设置你的密码。大部份网站一般都提供了根据Email找回密码的功能。实现此功能的思路:在登录界面添加一个“忘记密码“的链接,用户点击进去之后,输入用户名或Email,系统根据用户名或Email找出用户信息,并生成一个重新设置密码的链接发送到用户的邮箱中(生成链接的方式和生成帐户激活链接的方式一样),用户在邮箱中点击重设密码的链接,根据提示进入密码重设页面,重新输入新的密码即可。

功能实现步聚(帐号激活):

1、用户注册页面

用户名:
密码: ${errors.password}
确认密码: ${errors.password2}
email:

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);
}

}
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);
}

}
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;
}

}
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 = "xyang81@163.com";/*** 注册成功后,向用户发送帐户激活链接的邮件* @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() {@Overrideprotected 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();
}

}
7、实体类(User)
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、登录页面

${errors.loginError} 用户名:
密码: ${errors.password}
  忘记密码?  注册

2、发送重设密码申请的页面

${requestScope.sendMailMsg} 用户名/邮箱: ${requestScope.errorMsg}

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);
}

}
4、重新设置密码的页面

${errors.passwordError} 用户名:
新密码: ${errors.newPassword }
确认新密码: ${errors.newPassword2 }

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);
}

}
帐户激活操作流程:

1)、注册页面

2)、注册成功页面

3)、帐户未激活,登录后的界面

4)、前往邮箱中激活帐户

5)、激活成功

6)、帐户已激活,登录后的界面

忘记密码操作流程:

1)、登录页面(点击“忘记密码”链接,进入重设密码页面)

2、重设密码申请页面(输入用户名或邮箱,点击“提交”按钮)

3、重设密码申请成功页面

4、邮箱中重设密码的链接

5、重新设置密码页面

6、密码重新设置成功页面

源码下载地址:http://download.csdn.net/detail/xyang81/4510396
转自:[置顶] JavaMail学习笔记(七)、帐号激活与忘记密码 实例

帐号激活与忘记密码 实例相关推荐

  1. java web 邮箱激活 与 忘记密码(重置密码)

    推荐: java后台通用权限管理系统(springboot)(https://blog.csdn.net/zwx19921215/article/details/97806078) 推荐:java 个 ...

  2. 一个 SQL 同时验证帐号是否存在、密码是否正确

    出处:http://www.cnblogs.com/jacklondon/archive/2012/01/13/2321686.html近日偶尔看到一个很巧妙的 SQL 技巧,一个简单的 SQL 同时 ...

  3. 华为p50pro怎刷机华为p50怎么解锁华为p50pro能刷机吗华为p50强制刷机华为p50解账户锁华为P50pro解账户锁华为p50pro解锁账户华为p50怎么解锁帐号华为p50忘记解锁密码怎么办

    在刷机解锁过程中需要准备以下工具: 下面是用户华为p50pro手机解账户锁过程及用户桌面截图: 准备windwos系统电脑一台,有条件的用户可以找台配置好且插网线的电脑,这样会有效提高刷机解锁效率. ...

  4. 大话“用户注册激活,忘记密码”发送邮件功能

    鉴于最近有一部分童鞋留言关于"用户注册发送邮件激活"功能不太懂,在此我将用一片通俗易懂的话术简单说明一下"用户注册发送邮件激活"的大致原理和过程. 用户注册发送 ...

  5. php ftp 账号密码修改,月光软件站 - 编程文档 - 其他语言 - 用PHP即时添加,删除FTP帐号和更改FTP密码的函数...

    网上不知道有没有Serv-U FTP的接口,这类的资料,由于不知道Serv-U的加密方式,所以没有使用加密密码的方式,如果有人知道算法,麻烦你告诉我一声 $filepath是Serv-U的安装地址,$ ...

  6. 阿里云RAM子帐号授权单台ECS实例管理权限

    {"Version": "1","Statement": [{"Effect": "Allow",& ...

  7. 如何给自己各种帐号编一个安全又不会忘记的密码?

    [温馨提示:疑似钓鱼贴.不过也许是无意的.强烈建议大家不要公开自己所使用的密码.以及构建模式.不要使用公开的密码以及公开的密码模式.] [不要按照其他答案的模式来构建密码.无论是好意还是恶意公开,公开 ...

  8. mima.php密码找回,ecshop后台帐号密码忘记了如何找回

    在第一次使用ecshop商城的时候,部分人可能会忘记ecshop后台登陆密码,导致无法登录后台程序,苦苦思索也想不起来的情况下,我们可以自己去修改密码. 优易软件为大家整理修改密码的操作: defin ...

  9. 如何从路由器中查找ADSL帐号 [2007年4月13日]

    今天去取自己接手维护的一家店面维护网络,需要查看路由器的信息和接手那里的ADSL帐号.但是非常让我郁闷的是那里的网管吧ADSL帐号忘记了,虽然我可以通过路由器的用户名登录进去看到帐号,但是不知道密码也 ...

最新文章

  1. 1.9 Java数组和字符串的相互转换
  2. 开源PCRF、PCRF体验与PCRF实现
  3. springmvc如何使用视图解析器_SpringMVC工作原理
  4. mysql的命令行常用命令_mysql命令行常用命令
  5. php session 释放,php中删除Session和销毁Session的方法
  6. virsh命令 查看虚拟机镜像_kvm虚拟机操作相关命令及虚拟机和镜像密码修改
  7. 利用socket实现java程序自动关闭
  8. php 两位小数 00,php保存两位小数的几种要领引见_后端开发
  9. 34个漂亮的应用程序后台管理界面分享
  10. SpringSecurity前后端分离02(授权)
  11. html获取当前网页ip和端口,js获取当前访问者的IP地址和所属地市代码
  12. 周轶璐教授:服务好医生,如何更全面地了解数据、利用数据?
  13. P1359 租用游艇【Floyd】
  14. 操作系统二轮复习(进程的同步与互斥)
  15. HTML特效,旋转的正方体
  16. vue html 格式化,解决在写Vue时,格式化代码 属性自动换行的问题
  17. 计算机桌面颜色异常怎样修复,显示器颜色不正常如何调_电脑显示屏的颜色不对如何处理...
  18. 修改elementUI的el-popconfirm 气泡确认框样式不起效果
  19. 王菲语法11 动词(非谓语动词)
  20. linux中oracle导出dmp,linux下导入导出oracle的dmp文件

热门文章

  1. SQL 随机抽样的总结
  2. 什么都不会的应届生怎么找工作?
  3. [转载]45岁以后,外企的人都到去哪里了
  4. 掌握这些Java 后端面试题,20K妥妥的,400多人在学习
  5. 卷帘相机和全局相机的区别(Rolling Shutter Global Shutter)
  6. java 独木桥_独木桥 - pandaB - 博客园
  7. Script Insertion -客户端脚本植入攻击
  8. 密码学系列 - 棱镜门
  9. Android官方开发相关下载资源一揽子大汇总
  10. ER模型详解-陈氏模型