B070-项目实战-用户模块--手机注册

目录

      • 用户模块需求分析
      • 静态网站部署与调试
        • 两种前端项目的部署
        • 两种前端项目的调试(热部署)
        • 创建静态web项目
      • 注册分析与设计
        • 分析需求
        • 设计 界面设计(ui)设计表(后台) 流程设计(后台)
          • 三范式
          • 表设计
          • 流程设计
        • 相关技术准备
          • 1.随机字符串(用StrUtils工具类)
          • 2.springdata-redis
          • 3.Md5技术
          • 4.短信接口
      • 发送短信验证码
        • 前端页面准备
        • 发送短信后台
          • 搭建用户模块
          • 单独写公共可用的发短信接口
            • VerifycodeController
            • VerifycodeServiceImpl

用户模块需求分析

用户注册登录信息基本信息安全信息
用户登录账号登录扫码登录-自己app扫描页面三方登录-使用三方app(微信,qq,支付宝等)验证码登录-自己做  reids.set(logincode+phone,xxx)
用户管理
地址管理
收藏商品收藏店铺收藏服务收藏宠物收藏。。。。
足迹。。。。

静态网站部署与调试

两种前端项目的部署

vue-cli项目:pethome-admin(管理员的管理界面),用npm打包成静态项目后丢进Tomcat服务器跑
Css+div项目:pethome_web(用户访问门户网站),本身是静态项目可以直接丢进Tomcat服务器跑

两种前端项目的调试(热部署)

vue-cli项目可以npm run dev启动调试
传统静态项目需要安装 live-server服务器来调试,这个服务器很简单就是node的一个模块,
全局安装:npm install -g live-server,运行:live-server --port=80

创建静态web项目

拷贝amz_02_adp的two里项目资源到pethome-web目录下
复制home3.html到pethome-web根目录并改名为index.html作为首页
修改css和js引用路径

进入web子项目
全局安装:npm install -g live-server
启动调试:live-server --port=80

替换images图片

注册分析与设计

分析需求

注册分为:邮箱注册,和手机号注册,逻辑都是一样的,只是激活方式不一样。手机号注册:1)输入手机号2)获取验证码并且输入3)输入蜜马和确认蜜马4)完成注册

设计 界面设计(ui)设计表(后台) 流程设计(后台)

三范式

1NF:列的原子性,不可再拆分
2NF:行唯一,
3NF:如果一张表的数据能够通过其他表推导出来,不应该单独设计,应该通过外键的方式关联查询出来。

反3NF:有的时候我们为了增强查询效率,会设计一些冗余字段,变多表查询为单表查询。

表设计

在这里插入图片描述
在这里插入图片描述
注意:以后只要在eployee或user操作时涉及到登录信息都要同步操作logininfo。比如添加员工也要在logininfo添加一条记录,注册用户也要在logininfo中添加。同理删除或修改也要同步。

流程设计

见文档

相关技术准备

1.随机字符串(用StrUtils工具类)
import java.util.ArrayList;
import java.util.List;
import java.util.Random;/*** @author yaohuaipeng* @date 2018/10/26-16:16*/
public class StrUtils {/*** 把逗号分隔的字符串转换字符串数组** @param str* @return*/public static String[] splitStr2StrArr(String str,String split) {if (str != null && !str.equals("")) {return str.split(split);}return null;}/*** 把逗号分隔字符串转换List的Long** @param str* @return*/public static List<Long> splitStr2LongArr(String str) {String[] strings = splitStr2StrArr(str,",");if (strings == null) return null;List<Long> result = new ArrayList<>();for (String string : strings) {result.add(Long.parseLong(string));}return result;}/*** 把逗号分隔字符串转换List的Long** @param str* @return*/public static List<Long> splitStr2LongArr(String str,String split) {String[] strings = splitStr2StrArr(str,split);if (strings == null) return null;List<Long> result = new ArrayList<>();for (String string : strings) {result.add(Long.parseLong(string));}return result;}public static String getRandomString(int length) {String str = "0123456789";Random random = new Random();StringBuffer sb = new StringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(10);sb.append(str.charAt(number));}return sb.toString();}// 26字母+10数字public static String getComplexRandomString(int length) {String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";Random random = new Random();StringBuffer sb = new StringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(62);sb.append(str.charAt(number));}return sb.toString();}public static String convertPropertiesToHtml(String properties){//1:容量:6:32GB_4:样式:12:塑料壳StringBuilder sBuilder = new StringBuilder();String[] propArr = properties.split("_");for (String props : propArr) {String[] valueArr = props.split(":");sBuilder.append(valueArr[1]).append(":").append(valueArr[3]).append("<br>");}return sBuilder.toString();}}
2.springdata-redis

A 导入jar

<!--spirngboot springdata对redis支持-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

B 配置属性

spring:redis:database: 0host: 127.0.0.1port: 6379password: 123456jedis:pool:max-wait: 2000msmin-idle: 2max-idle: 8

启动redis服务:找到redis安装目录,cmd运行,redis-server.exe redis.windows.conf
C 编写测试类(基于springboot的测试类(继承BaseTest即可),用springdataredis提供的bean直接操作redis)

public class RedisTest extends BaseTest {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void test(){redisTemplate.opsForValue().set("ceshi", "搞一条数据");System.out.println(redisTemplate.opsForValue().get("ceshi"));}
}
3.Md5技术

不可逆加密技术,只能加密不能解密。 只能做比对,一般用来加密用户登录蜜马。
我们要做的是把传入的蜜马进行加密和然后数据库查询出来的密文进行比对判断蜜马是否正确。

盐值:同一种加密算法,由于不同的盐值,加密出来就不一样。
每个用户都有自己盐值,就算是相同的蜜马,两个用户加密出来的密文也不一样。

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class MD5Utils {/*** 加密* @param context  明文*/public static String encrypByMd5(String context) {try {  MessageDigest md = MessageDigest.getInstance("MD5");md.update(context.getBytes());//update处理byte [] encryContext = md.digest();//调用该方法完成计算int i;StringBuffer buf = new StringBuffer("");for (int offset = 0; offset < encryContext.length; offset++) {//做相应的转化(十六进制)i = encryContext[offset];if (i < 0) i += 256;if (i < 16) buf.append("0");buf.append(Integer.toHexString(i));}return buf.toString();} catch (NoSuchAlgorithmException e) {// TODO Auto-generated catch block  e.printStackTrace();return  null;}  }public static void main(String[] args) {//1.准备需要加密的蜜马String pwd = "1";//2 准备盐值String salt = StrUtils.getComplexRandomString(32);//2.加密  + 盐String pwdMd5 = MD5Utils.encrypByMd5(pwd + salt);// 将盐值和秘文存储到数据System.out.println(pwdMd5);//模拟登陆蜜马校验String pwdStr = pwd;String saltTem = salt;//相当于从数据库查询出来String pwdTmpMd5 = MD5Utils.encrypByMd5(pwdStr + saltTem);System.out.println("==="+pwdTmpMd5);if(pwdTmpMd5.equals(pwdMd5)){System.out.println("登陆成功");}else{System.out.println("蜜马错误");}}}
4.短信接口

http://sms.webchinese.com.cn/Rates.shtml
用户信息修改,修改短信秘钥

导入依赖包

        <dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.1</version></dependency>

代码应用(工具类 常量类)

	public static void sendsms(String phones, String message) throws IOException {HttpClient client = new HttpClient();PostMethod post = new PostMethod("https://utf8api.smschinese.cn/");post.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");//在头文件中设置转码NameValuePair[] data ={ new NameValuePair("Uid", "mingfeng"),new NameValuePair("Key", "d41d8cd98f00b204e980"),new NameValuePair("smsMob",phones),new NameValuePair("smsText",message)};post.setRequestBody(data);client.executeMethod(post);Header[] headers = post.getResponseHeaders();int statusCode = post.getStatusCode();System.out.println("statusCode:"+statusCode); //HTTP状态码for(Header h : headers){System.out.println(h.toString());}String result = new String(post.getResponseBodyAsString().getBytes("utf-8"));System.out.println(result);  //打印返回消息状态post.releaseConnection();}

发送短信验证码

前端页面准备

1.拷贝register.html到根目录,更新引用路径

2.index.html设置在新标签页打开登录界面: target=“_blank”

	<div class="menu-hd"><a href="#" target="_top" class="h">亲,请登录</a><a href="register.html" target="_blank">免费注册</a></div><div class="member-logout"><a class="am-btn-warning btn" href="login.html">登录</a><a class="am-btn-warning btn" target="_blank" href="register.html">注册</a></div>

3.静态项目引入js插件vue和axios
拷贝ph-admin\node_modules里的axios和vue到ph-web/js/plugin目录里并在register.html页面引入

        <!--引入vue和axios--><script src="js/plugin/vue/dist/vue.min.js"></script><script src="js/plugin/axios/dist/axios.js"></script><!--全局使用--><script src="js/common.js"></script><!-- 局部使用<script type="text/javascript">//配置axios的全局基本路径/*axios.defaults.baseURL='/api' 前端解决跨域*/axios.defaults.baseURL='http://localhost:8080/'//全局属性配置,在任意组件内可以使用this.$http获取axios对象Vue.prototype.$http = axios</script>-->

在js目录下新建common.js

//配置axios的全局基本路径
/*axios.defaults.baseURL='/api' 前端解决跨域*/
axios.defaults.baseURL='http://localhost:8080/'
//全局属性配置,在任意组件内可以使用this.$http获取axios对象
Vue.prototype.$http = axios

绑定div节点

<div class="am-tab-panel" id="myDiv">

写vue.js

<script type="text/javascript">new Vue({el:"#myDiv",mounted(){alert(this.$http)}})
</script>

获取的a标签换为按钮(方便置灰和显示秒数倒计时),绑定方法

<!--<a class="btn" href="javascript:void(0);" οnclick="sendMobileCode();" id="sendMobileCode"><span id="dyMobileButton">获取</span></a>-->
<button type="button" @click="sendMobileCode">获取</button>
		methods:{sendMobileCode(){alert(123)}},

点击获取拿到手机号

<input type="tel" v-model="phoneUserForm.phone" name="" id="phone" placeholder="请输入手机号">
<script type="text/javascript">new Vue({el:"#myDiv",data:{phoneUserForm:{phone:18696148335}},methods:{sendMobileCode(){alert(this.registerForm.phone)}},mounted(){// alert(this.$http)}})
</script>
<script type="text/javascript">new Vue({el:"#myDiv",data:{phoneUserForm:{phone:""}},methods:{sendMobileCode(){//1.判断手机号不为空if(!this.phoneUserForm.phone){alert("手机号不能为空");return;}//2.获取按钮 禁用按钮 发送时灰化不能使用 发送成功倒计时60才能使用 如果发送失败立即可以发送var sendBtn = $(event.target);sendBtn.attr("disabled",true);this.$http.post('/verifycode/smsCode',{"phone":this.phoneUserForm.phone}).then((res) => {console.log(res);var ajaxResult = res.data;if(ajaxResult.success){alert("手机验证码已经发送到您的手机,请在3分钟内使用");//3.1.发送成:倒计时var time = 60;var interval = window.setInterval( function () {//每一条倒计时减一time = time - 1 ;//把倒计时时间搞到按钮上sendBtn.html(time);//3.2.倒计时完成恢复按钮if(time <= 0){sendBtn.html("重发");sendBtn.attr("disabled",false);//清除定时器window.clearInterval(interval);}},1000);}else{//3.3.发送失败:提示,恢复按钮sendBtn.attr("disabled",false);alert("发送失败:"+ajaxResult.message);}});}},mounted(){// alert(this.$http)}})
</script>

发送短信后台

搭建用户模块

User,loginInfo
搭建完模块后记得yml配置domain和query的扫描路径(别名)

单独写公共可用的发短信接口
VerifycodeController
@RestController
@RequestMapping("/verifycode")
public class VerifycodeController {@Autowiredprivate IVerifycodeService verifycodeService;/*** 发送短信验证码* @param phone  给谁发送  只是允许传入一个手机号* @return*/@PostMapping("/smsCode")public AjaxResult sendSmsCode(@RequestBody String phone){try {verifycodeService.sendSmsCode(phone);return AjaxResult.me();} catch (BusinessException e) {return AjaxResult.me().setMessage("发送失败!"+e.getMessage());}catch (Exception e) {e.printStackTrace();return AjaxResult.me().setMessage("系统繁忙,稍后重试!!");}}
}
VerifycodeServiceImpl
		//1.校验//1.1手机号空校验//1.2不能被注册//2.判断是否存在验证码(从redis中获取电话对应的验证码)//2.1 存在//2.1.1 判断是否过了重发时间(1分钟)//2.1.1.1 如果没过重发时间。报错:请勿重复发送//2.1.1.2 如果过了,使用原来还没过期的验证码,刷新过期时间//2.2 不存在//2.2.1直接生成验证码//3 保存验证码到redis  设置过期时间//4 发送短信(使用工具类掉短信接口即可)
@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class VerifycodeServiceImpl implements IVerifycodeService {@Autowiredprivate IUserService userService;@Autowiredprivate RedisTemplate redisTemplate;@Overridepublic void sendSmsCode(String phone) {//1.校验//1.1手机号空校验if(!StringUtils.hasLength(phone)){throw new BusinessException("手机号不能为空!");}//1.2不能被注册User user = userService.loadUserByPhone(phone);if(user != null){throw new BusinessException("用户已经你存在!");}//2.判断是否存在验证码(从redis中获取电话对应的验证码)Object codeObj = redisTemplate.opsForValue().get(UserConstant.USER_VERFIY_CODE+":"+phone);String code = "";if(codeObj !=null){//2.1 存在String value =(String)codeObj;String timeStr = value.split(":")[1];//时间戳//2.1.1 判断是否过了重发时间(1分钟)if(System.currentTimeMillis()-Long.valueOf(timeStr) <= 1*60*1000){//2.1.1.1 如果没过重发时间。报错:请勿重复发送throw new BusinessException("请勿重复发送验证码!!!");}//2.1.1.2 如果过了,使用原来还没过期的验证码,刷新过期时间code = value.split(":")[0];//验证码}else{//2.2 不存在//2.2.1直接生成验证码code = StrUtils.getComplexRandomString(4);}//拼接存储验证码的格式String codeValue = code + ":" + System.currentTimeMillis();//3 保存验证码到redis  设置过期时间redisTemplate.opsForValue().set(UserConstant.USER_VERFIY_CODE+":"+phone, codeValue, 3, TimeUnit.MINUTES);//4 发送短信(使用工具类掉短信接口即可)/*SmsUtils.sendSms(phone, "您的验证码是:"+code+"; 请在3分钟内使用!");*/System.out.println("您的验证码是:"+code+"; 请在3分钟内使用!");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/3791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小白入门C#编写MVC登录小案例

一、C#编写MVC登录小案例 &#x1f680;1. 新建MVC项目。 &#x1f680;2. 在Models文件夹下创建一个User类&#xff0c;包含登录所需要的用户名和密码属性。 namespace MvcLogin.Models {public class User{public string UserName{get; set;}public string Password{get;se…

遥感目标检测(1)--R3Det

目录 一、概述 二、三个挑战 三、网络架构​ 1、旋转RetinaNet 2、精细化旋转RetinaNet 3、与RoIAlign&#xff08;感兴趣区域插值&#xff09;进行比较 4、消融实验与对比实验 一、概述 R3Det论文中提到一个端到端的精细化的单级旋转检测器&#xff0c;通过从粗到细的逐…

Maven —— 项目管理工具

前言 在这篇文章中&#xff0c;荔枝会介绍如何在项目工程中借助Maven的力量来开发&#xff0c;主要涉及Maven的下载安装、环境变量的配置、IDEA中的Maven的路径配置和信息修改以及通过Maven来快速构建项目。希望能对需要配置的小伙伴们有帮助哈哈哈哈~~~ 文章目录 前言 一、初…

Unity根据目标点的位置计算Input输入

当给一个目标点&#xff0c;如果目标直接去目标点我们可以直接让position指向目标点的position。 如果是转换输入呢&#xff1f; 举例&#xff1a;例如一个人物动画里有两个参数X和Y&#xff0c;X&#xff08;- 1 &#xff0c;1) 表示向左走和向右走&#xff0c;Y (-1 , 1) 向…

leetcode 101.对称二叉树

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;对称二叉树 思路&#xff1a; 这道题和 leetcode 100.相同的树 类似&#xff0c;是上一道的变形题。✨leetcode 100.相同的树 代码链接&#xff1a;【往期文章】leetcode 100.相同的树。这道题把根的左子树和右子树看作两…

回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测

回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测 目录 回归预测 | MATLAB实现基于BiGRU-AdaBoost双向门控循环单元结合AdaBoost多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于B…

Vue列表排序

开始前先回顾一下sort排序用法&#xff1a; 定义一串数组arr&#xff0c;使用sort排序&#xff0c;会收到前后两个数据项设置两个参数a&#xff0c;b。 注意&#xff1a;a-b 是升序 b-a 是降序 a-b升序&#xff1a; <script>let arr [12,11,2,5,76,33]arr.sort((a,b…

园区能源控制管理系统

园区能源控制管理系统是一种能够实现对园区内能源消耗、供应和分配进行实时监控、管理和控制的系统。该系统通过对园区内各种能源设备的数据采集、处理和分析&#xff0c;为管理者提供实时的能源使用情况和数据分析&#xff0c;从而帮助管理者制定科学的能源管理策略和节能措施…

TMS FlexCel for VCL FMX Crack

TMS FlexCel for VCL & FMX Crack 强大、广泛和灵活的组件套件&#xff0c;用于VCL和FireMonkey的本地Excel报告、文件生成和操作。 FlexCel for VCL/FireMonkey是一套允许操作Excel文件的Delphi组件。它包括一个广泛的API&#xff0c;允许本地读/写Excel文件。如果您需要在…

华为云CodeArts Check IDE插件体验之旅

1 开发者的思考 近年来&#xff0c;ChatGPT的来临像一场突然出现的风暴&#xff0c;程序员是否马上被取代的担忧出现在媒体上了&#xff0c;作为软件开发小白&#xff0c;前不久我也陷入了这样的深思之中&#xff0c;但认真的想了下&#xff0c;ChatGPT就如自动驾驶一样&#…

NAS 问题处理记录

在解决自动配网的过程中&#xff0c;突然NAS不给力&#xff0c;偏偏这个时间找事情。上面这两个问题&#xff0c;说不复杂也不复杂&#xff0c;主要是自己在完全远程处理&#xff0c;很多不方便。当然少不了师弟的助攻&#xff0c;很感谢我的师弟帮忙&#xff0c;实验室的网络不…

ubuntu20.04系统安装使用labelme标注数据集

一、Anaconda的安装 请参考&#xff1a;MediapipeVSCodeAnaconda 实时检测手部关键点并保存视频_苦瓜汤补钙的博客-CSDN博客 二、Labelme的安装 1.打开终端创建虚拟环境 # 创建labelme的环境 conda create -n labelme python3.9 输入“y”&#xff0c;然后回车。 2.激活虚拟…

基于单片机的智能路灯控制系统人体感应灯光控制系统的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;LCD1602液晶显示当前时间、年月日、时分秒&#xff1b;按键看看有设置自动手动模式&#xff1b;3路红外探头用来感应当前3个区域是否有人&#xff1b;按键可以设置当前时间、开启和关闭教室灯光时间&#xff1b;在手动模式下&#…

【JavaEE面试题(九)线程安全问题的原因和解决方案】

多线程-初阶 4. 多线程带来的的风险-线程安全 (重点)4.1 观察线程不安全原因是 1.load 2. add 3. save 4.2 线程安全的概念4.3 线程不安全的原因最根本的是 操作系统对线程的调度是随机的★1. 修改共享数据&#xff08;多个线程修改同一个变量&#xff09;★2. 操作不是原子性★…

园区水电能源管理系统平台

园区水电能源管理系统平台是一种集成了水电能源监测、管理和优化功能的平台&#xff0c;旨在帮助园区管理者实现对水电资源的实时监测、合理节能和优化使用。随着能源需求的不断增长和能源价格的不断攀升&#xff0c;园区管理者面临着越来越大的节能减排压力。因此&#xff0c;…

IDEA中设置鼠标滚轮修改字体大小

IDEA中设置鼠标滚轮修改字体大小&#xff1f; 选择File--Settings--Editor--General&#xff0c;把 Mouse Control 前的对勾勾选 后点击 OK 即可。 勾选此设置后&#xff0c;增加 Ctrl 鼠标滚轮 快捷键来控制代码字体大小显 示。字体随时可以放大缩小~~可真好用呢~

OpenCv之图像轮廓

目录 一、图像轮廓定义 二、绘制轮廓 三、计算轮廓面积与周长 一、图像轮廓定义 图像轮廓是具有相同颜色或灰度的连续带你的曲线.轮廓在形状分析和物体的检测和识别中很有用 轮廓的作用: 用于图形分析物体的识别与检测 注意点: 为了检测的准确性&#xff0c;需要先对图像…

什么是 XSS 攻击,攻击原理是什么

什么是 XSS 攻击&#xff1f; XSS&#xff08;Cross-Site Scripting&#xff09;攻击是一种常见的 Web 安全漏洞&#xff0c;其攻击目标是 Web 应用程序中的用户&#xff0c;攻击者通过在 Web 页面中植入恶意脚本&#xff0c;从而实现窃取用户敏感信息、篡改用户数据等目的。 …

线程与信号

1. 进程内所有线程共享信号处理配置&#xff0c;故信号配置可以全部放在主线程内。 2. 每个线程有自己的信号掩码sigset_t&#xff0c;线程创建时继承创建时线程的信号掩码。 3. 触发信号处理函数按创建线程顺序分配给当前空闲线程&#xff0c;信号处理函数内是可以阻塞的。 …

云计算名词-IaaS,PaaS,SaaS

在学习分布式的过程中&#xff0c;知道了PaaS这个词儿&#xff0c;但是不知道是什么意思。从网上查询了之后&#xff0c;做了简单的了解。这里简单记录一下&#xff0c;方面之后的查阅。 IAAS&#xff08;Infrastructure-as-a-Service&#xff09;基础设施即服务 网上的定义是…