目录
一.网站首页
二.编写注册界面
三.生成验证码
四.注册流程
五.编写注册方法
六.发送邮件配置
一.网站首页
static/frontdesk下存放前台静态资源,而templates/frontdesk是前台页面
二.编写注册界面
在上个界面点击注册就可以跳转到注册界面
在这里遇到一个bug,就是从index.html(上面那个页面)进行跳转到注册界面跳不过去,状态码500,报错是
template might not exist or might not be accessible by any of the configured
这是模板不存在或者找不到register.html这个文件,我尝试了很多方法,但是都行不通,最后我随便在配置文件的classpath:/template后面加了个/就好了,即变成了classpath:/templates/
三.生成验证码
验证码的作用是验证操作者是否是真人,避免机器操作恶意提交。它是后台随机生成的一串字符串,但我们不能将该字符串直接传到前台,否则机器直接读到字符串,验证码将没有任何意义。
一般在后台生成验证码后, 一方面将验证码保存到session中,另一方面将验证码做成一张图片,将图片传到前台。用户认出验证码后,输入验证码传到后台,如果正确即可判断操作者为真人。.
1.引入生成验证码的servlet
/**
* 验证码
*/
@WebServlet("/frontdesk/checkCode")
public class CheckCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {
//服务器通知浏览器不要缓存
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");
//在内存中创建一个长80,宽30的图片,默认黑色背景
//参数一:长
//参数二:宽
//参数三:颜色
int width = 80;
int height = 30;
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取画笔
Graphics g = image.getGraphics();
//设置画笔颜色为灰色
g.setColor(Color.GRAY);
//填充图片
g.fillRect(0,0, width,height);
//产生4个随机验证码,12Ey
String checkCode = getCheckCode();
//将验证码放入HttpSession中
request.getSession().setAttribute("checkCode",checkCode);
//设置画笔颜色为黄色
g.setColor(Color.YELLOW);
//设置字体的小大
g.setFont(new Font("黑体",Font.BOLD,24));
//向图片上写入验证码
g.drawString(checkCode,15,25);
//将内存中的图片输出到浏览器
//参数一:图片对象
//参数二:图片的格式,如PNG,JPG,GIF
//参数三:图片输出到哪里去
ImageIO.write(image,"PNG",response.getOutputStream());
}
/**
* 产生4位随机字符串
*/
private String getCheckCode() {
String base = "0123456789ABCDEFGabcdefg";
int size = base.length();
Random r = new Random();
StringBuffer sb = new StringBuffer();
for(int i=1;i<=4;i++){
//产生0到size-1的随机值
int index = r.nextInt(size);
//在base字符串中获取下标为index的字符
char c = base.charAt(index);
//将c放入到StringBuffer中去
sb.append(c);
}
return sb.toString();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
}
运行项目:
验证码点击一下就会更新。
四.注册流程
上面的流程图和手机验证码是一个道理,都能确认邮箱或者手机号的真实性。
为了保证用户注册的信息是真实的,往往在用户注册后不能直接登录,而需要用户激活后才
能登录。用户注册激活的步骤如下:
- 用户在页面填写个人信息,发送到后端代码。
- 后端验证数据后保存用户信息,但此时用户的状态为false,还不能登录。
- 后端拿到用户输入的邮箱,给用户邮箱发送一段随机字符串, 并将该字符串保存到数据库的用户表中。
- 用户登录个人邮箱,点击随机字符串访问项目,项目将该拥有字符串的用户状态变为true,此时用户即可登录。
五.编写注册方法
1.编写前台用户的MemberMapper
public interface MemberMapper extends BaseMapper<Member> {
}
2.由于注册方法结果很多,我们注册方法需要返回的是否注册成功,如果失败需要返回失败原因。我们要在bean目录下创建一个实体类Result,该实体类可以封装返回的数据。
// 结果对象
@Data
@AllArgsConstructor
public class Result {
private boolean flag; // 结果
private String message; // 提示信息
private Object data; // 返回数据
public Result(boolean flag,String message){
this(flag,message,null);
}
}
3.编写MemberService
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.first.travel.bean.Result;
import com.first.travel.mapper.MemberMapper;
import com.first.travel.pojo.Member;
import com.first.travel.util.MailUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Service
public class MemberService {
@Autowired
private MemberMapper memberMapper;
//@Autowired
//private BCryptPasswordEncoder encoder;
@Autowired
private MailUtils mailUtils;
@Value("${project.path}")
private String projectPath;
// 注册
public Result register(Member member) {
// 1.保存用户
// 验证用户名是否重复
QueryWrapper<Member> queryWrapper = new QueryWrapper();
queryWrapper.eq("username", member.getUsername());
List<Member> members = memberMapper.selectList(queryWrapper);
if (members.size() > 0) {
return new Result(false, "用户名已存在");
}
// 验证手机是否重复
QueryWrapper<Member> queryWrapper1 = new QueryWrapper();
queryWrapper1.eq("phoneNum", member.getPhoneNum());
List<Member> members1 = memberMapper.selectList(queryWrapper1);
if (members1.size() > 0) {
return new Result(false, "手机已存在");
}
// 验证邮箱是否重复
QueryWrapper<Member> queryWrapper2 = new QueryWrapper();
queryWrapper2.eq("email", member.getEmail());
List<Member> members2 = memberMapper.selectList(queryWrapper2);
if (members2.size() > 0) {
return new Result(false, "邮箱已存在");
}
// 加密密码
String password = member.getPassword();
//password = encoder.encode(password);
member.setPassword(password);
// 设置用户状态为false
member.setActive(false);
// 2.发送激活邮件
// 生成激活码
String activeCode = UUID.randomUUID().toString();
// 给用户的邮箱发送一封邮件,该邮件包含一个链接,链接中包含激活码
String activeUrl = projectPath + "/frontdesk/member/active?activeCode=" + activeCode;
String text = "恭喜您注册成功!<a href = '" + activeUrl + "'>点击激活</a>完成账号认证";
mailUtils.sendMail(member.getEmail(), text, "旅游网激活邮件");
// 保存激活码,激活时比对
member.setActiveCode(activeCode);
// 保存用户
memberMapper.insert(member);
return new Result(true, "注册成功!");
}
// 激活用户
public String active(String activeCode) {
// 根据激活码查询用户
QueryWrapper<Member> queryWrapper = new QueryWrapper();
queryWrapper.eq("activeCode", activeCode);
Member member = memberMapper.selectOne(queryWrapper);
// 没有找到用户:激活失败
if (member == null) {
return "激活失败!激活码错误!";
} else {
member.setActive(true);
memberMapper.updateById(member);
return "激活成功,请<a href='" + projectPath + "/frontdesk/login'>登录</a>";
}
}
public Result login(String name, String password) {
Member member = null;
// 根据用户名查询
if (member == null) {
QueryWrapper<Member> queryWrapper = new QueryWrapper();
queryWrapper.eq("username", name);
member = memberMapper.selectOne(queryWrapper);
}
// 根据手机查询
if (member == null) {
QueryWrapper<Member> queryWrapper = new QueryWrapper();
queryWrapper.eq("phoneNum", name);
member = memberMapper.selectOne(queryWrapper);
}
// 根据邮箱查询
if (member == null) {
QueryWrapper<Member> queryWrapper = new QueryWrapper();
queryWrapper.eq("email", name);
member = memberMapper.selectOne(queryWrapper);
}
// 没有查询到用户
if (member == null) {
return new Result(false, "用户名或密码错误");
}
// 验证密码
// boolean flag = encoder.matches(password, member.getPassword());
// if (!flag) {
// return new Result(false, "用户名或密码错误");
// }
// 验证是否激活
if (!member.isActive()) {
return new Result(false, "用户未激活,请登录邮箱激活用户");
}
return new Result(true, "登录成功", member);
}
}
controller:
import com.first.travel.bean.Result;
import com.first.travel.pojo.Member;
import com.first.travel.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpSession;
@Controller
@RequestMapping("/frontdesk/member")
public class MemberController {
@Autowired
private MemberService memberService;
@RequestMapping("/register")
public ModelAndView register(Member member, String checkCode, HttpSession session){
ModelAndView modelAndView = new ModelAndView();
// 判断验证码是否正确
String sessionCheckCode = (String) session.getAttribute("checkCode");
if (!sessionCheckCode.equalsIgnoreCase(checkCode)){
modelAndView.addObject("message","验证码错误");
modelAndView.setViewName("/frontdesk/register");
return modelAndView;
}
// 注册
Result result = memberService.register(member);
if (!result.isFlag()){ // 注册失败
modelAndView.addObject("message",result.getMessage());
modelAndView.setViewName("/frontdesk/register");
}else { // 注册成功
modelAndView.setViewName("/frontdesk/register_ok");
}
return modelAndView;
}
@RequestMapping("/active")
public ModelAndView active(String activeCode){
ModelAndView modelAndView = new ModelAndView();
String active = memberService.active(activeCode);
modelAndView.addObject("message",active);
modelAndView.setViewName("/frontdesk/active_result");
return modelAndView;
}
@RequestMapping("/login")
public ModelAndView login(String name,String password,HttpSession session){
ModelAndView modelAndView = new ModelAndView();
Result result = memberService.login(name, password);
if (!result.isFlag()){ // 登录失败
modelAndView.addObject("message",result.getMessage());
modelAndView.setViewName("/frontdesk/login");
}else{ // 登录成功
// 将用户信息存入session
session.setAttribute("member",result.getData());
modelAndView.setViewName("redirect:/frontdesk/index");
}
return modelAndView;
}
@RequestMapping("/logout")
public String logout(HttpSession session){
session.removeAttribute("member");
return "redirect:/frontdesk/index";
}
}
六.发送邮件配置
在用户注册成功后,要向用户的邮箱发送一封激活邮件 ,发送邮件需要在系统中配置发件
人,同学们使用自己的邮箱作为发件人即可。
1.配置邮箱第三方登录。
我们在系统中使用邮箱发送邮件属于第三方登录,而市面.上的邮箱默认是不能第三方登
录的。我们需要登录邮箱,配置第三方登录。以QQ邮箱配置举例:
开启第三方登录服务,点击开启
按要求发送短信
然后在配置文件中配置:
注意发件人密码就是上面的授权码。
发送邮件的工具类:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
/**
* 发邮件工具类
*/
@Component
public final class MailUtils {
@Value("${mail.user}")
private String USER; // 发件人邮箱地址
@Value("${mail.password}")
private String PASSWORD; // 如果是qq邮箱可以使户端授权码
/**
* 发送邮件
* @param to 收件人邮箱
* @param text 邮件正文
* @param title 标题
*/
public boolean sendMail(String to, String text, String title){
try {
final Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", "smtp.qq.com");
// 发件人的账号
props.put("mail.user", USER);
//发件人的密码
props.put("mail.password", PASSWORD);
// 构建授权信息,用于进行SMTP进行身份验证
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// 用户名、密码
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);
// 设置发件人
String username = props.getProperty("mail.user");
InternetAddress form = new InternetAddress(username);
message.setFrom(form);
// 设置收件人
InternetAddress toAddress = new InternetAddress(to);
message.setRecipient(Message.RecipientType.TO, toAddress);
// 设置邮件标题
message.setSubject(title);
// 设置邮件的内容体
message.setContent(text, "text/html;charset=UTF-8");
// 发送邮件
Transport.send(message);
return true;
}catch (Exception e){
e.printStackTrace();
}
return false;
}
}
引入邮件依赖:
<!--发送邮件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
测试类:
@SpringBootTest
class TravelApplicationTests {
@Autowired
private MailUtils mailUtils;
@Test
void contextLoads() {
//填自己的邮箱地址
mailUtils.sendMail("10208@qq.com","这是一封测试邮件","测试");
}
}
开始注册:
然后右下角一般会有弹窗(收到了邮箱验证码),咱们登录QQ邮箱查看,果然收到了一封激活邮件
到数据库的member表里可以看到咱们注册的用户信息都在里面,而且只有激活之后active才会变成1(刚注册的时候是0)
蒹葭苍苍,白露为霜。所谓伊人,在水一方。
溯洄从之,道阻且长。溯游从之,宛在水中央。