目录

一.网站首页

二.编写注册界面

三.生成验证码

四.注册流程

五.编写注册方法

六.发送邮件配置


一.网站首页

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个随机验证码,12EyString 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);}
}

运行项目:

验证码点击一下就会更新。

四.注册流程

上面的流程图和手机验证码是一个道理,都能确认邮箱或者手机号的真实性。

为了保证用户注册的信息是真实的,往往在用户注册后不能直接登录,而需要用户激活后才
能登录。用户注册激活的步骤如下:

  1. 用户在页面填写个人信息,发送到后端代码。
  2. 后端验证数据后保存用户信息,但此时用户的状态为false,还不能登录。
  3. 后端拿到用户输入的邮箱,给用户邮箱发送一段随机字符串, 并将该字符串保存到数据库的用户表中。
  4. 用户登录个人邮箱,点击随机字符串访问项目,项目将该拥有字符串的用户状态变为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 {@Autowiredprivate MemberMapper memberMapper;//@Autowired//private BCryptPasswordEncoder encoder;@Autowiredprivate 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);// 设置用户状态为falsemember.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 {@Autowiredprivate 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{ // 登录成功// 将用户信息存入sessionsession.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() {@Overrideprotected 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 {@Autowiredprivate MailUtils mailUtils;@Testvoid contextLoads() {//填自己的邮箱地址mailUtils.sendMail("10208@qq.com","这是一封测试邮件","测试");}
}

开始注册:

然后右下角一般会有弹窗(收到了邮箱验证码),咱们登录QQ邮箱查看,果然收到了一封激活邮件

到数据库的member表里可以看到咱们注册的用户信息都在里面,而且只有激活之后active才会变成1(刚注册的时候是0)

蒹葭苍苍,白露为霜。所谓伊人,在水一方。
溯洄从之,道阻且长。溯游从之,宛在水中央。

项目实战之旅游网(十)前台用户注册相关推荐

  1. 项目实战之旅游网(七)后台分类管理 后台产品管理(上)

    目录 一.后台分类管理 二.后台产品管理(上) 1.产品列表 2.新增产品 3.富文本编辑器 一.后台分类管理 mapper层: public interface CategoryMapper ext ...

  2. 项目实战之旅游网(五)后台角色管理(下) 后台权限管理

    目录 一.后台角色管理(下) 1.查询角色权限 2.修改角色权限 3.优化侧边栏菜单 二.后台权限管理 1.权限列表 2.新增权限 3.修改权限 4.删除权限 一.后台角色管理(下) 1.查询角色权限 ...

  3. 【Android项目实战 | 从零开始写app(十二)】实现app首页智慧服务热门推荐热门主题、新闻

    说在前面,由于各种adapter,xml布局,bean实体类,Activity,也为了让看懂,代码基本都是"简单粗暴直接不好看",没啥okhttp和util工具类之类的封装,本篇幅 ...

  4. Spring Boot + vue-element 开发个人博客项目实战教程(二十五、项目完善及扩展(前端部分))

    ⭐ 作者简介:码上言 ⭐ 代表教程:Spring Boot + vue-element 开发个人博客项目实战教程 ⭐专栏内容:零基础学Java.个人博客系统 ⭐我的文档网站:http://xyhwh- ...

  5. 【网络通信 -- 直播】项目实战记录 -- 弱网模拟工具

    [网络通信 -- 直播]项目实战记录 -- 弱网模拟工具 [1]Windows 系统中弱网模拟工具 Windows 系统中可以使用 Clumsy 工具模拟弱网环境 Lag(延迟),把数据包缓存一段时间 ...

  6. 基于eclipse的android项目实战—博学谷(十九)播放不同视频(本地视频)

    BoXueGu资源下载链接: https://download.csdn.net/download/hyh/19477319 BoXueGu图片资源下载(免费): https://yuyunyaohu ...

  7. 基于eclipse的android项目实战—博学谷(十八)播放不同视频(网络视频)

    相信经过了这么长时间,小伙伴们应该都发现了博学谷这个项目存在问题,播放视频的时候,无论播放任何一个章节,他播放的视频都只是一个,也就是VideoPlayActivity.java里面写死的那个(myv ...

  8. DIV+CSS布局实战---海南旅游网

    代码: liyouwang.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  9. 项目实战---模拟凡客网

    项目描述:本项目是对凡客网(http://www.vancl.com/)的一个模拟开发 主要开发了首页,衬衫,T恤,卫衣,外套,针织 衫,裤装,鞋,登录注册等页面 效果如下: (演示格式为GIF,若网 ...

最新文章

  1. 树上分治详解 超级详细(附带例题 poj1741(给了题目))
  2. ansible企业级自动化运维工具
  3. PMCAFF问答龙虎榜,大神云集,等你挑战
  4. boost::contract模块实现overload的测试程序
  5. CentOS7.3的基本配置(建议学习用)
  6. linux 装jdk出错,redhat linux 9.0安装jdk出错,该如何解决
  7. DOM节点的获取及创建
  8. 从入门到入土:Python爬虫学习|实例练手|爬取LOL全英雄信息及技能||异步加载|初级难度反扒处理|寻找消失的API
  9. Civil3D二次开发常见问题总结
  10. Java编程:中缀表达式转后缀表达式
  11. [Swift]LeetCode609. 在系统中查找重复文件 | Find Duplicate File in System
  12. iOS 端 HTTP 抓包分析工具推荐-Thor
  13. 生成pdf设置中文字体出错 \simsun.ttc' with 'Identity-H' is not recognized或者type of font{0} is not recognized
  14. 81页智慧城市-大数据决策与支撑平台解决方案
  15. Android APK 反编译工具 JADX
  16. Dynamics CRM 365 - 零基础入门学习后端插件语法总结(样例使用方法)
  17. 阿里云商标注册流程步骤-阿里云商标自助注册申请步骤...
  18. android toast 自定义view,分享Android中Toast的自定义使用
  19. 超声波清洗机 - 拆机与逆向工程
  20. 积极的心态带动积极的行为

热门文章

  1. JS 正则匹配中日韩字符
  2. linux自动化安装u盘,使用u盘自动化安装centos的例子
  3. 静态图片转3D动态GIF/视频
  4. python求两条线段的交点
  5. 亚马逊云科技中国有限预览服务即将来临
  6. 乳腺癌病理图像分类之A Novel Architecture to Classify Histopathology Images Using CNN之二--模型代码复现
  7. Python图形界面库(GUI)各类库的优缺点简介
  8. 大学四年里 你要走遍全国吗?!(自助游信息整理大集合)
  9. 逃不掉的是回忆,忘不了的是曾经:伤感日志
  10. 快速选择——python