OJ项目【登录】——验证码、失败登录多次账户冻结、用户密码加密,我是如何实现的?
目录
前言
1、验证码
1.1、引入pom
1.2、前端核心代码
1.3、后端核心代码
2、账户冻结
2.1、思路:
2.2、核心代码示例:
3、密码加密——加盐算法
3.1、思路:
3.2、代码实现示例:
4、小结:展示我的项目
4.1、后端代码:
4.2、效果展示:
前言
前端代码,我只展示核心代码,其他的代码需要小伙伴们自行编写哦~
项目是Spring项目,需要小伙伴们有一点点Spring基础~
我这些实现方式,只是一个参考,并不是最优解~
1、验证码
验证码这里,我们使用的是easy-captcha,对他感兴趣的伙伴,可以自行查一下资料,下面,我只实现4位验证码,有字母和数字组成的这种~
1.1、引入pom
<!-- 验证码 --><dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId><version>1.6.2</version></dependency>
1.2、前端核心代码
准备一个html:
<div class="row"><input type="text" id="authCode" class="form-control" name="verifyCode" placeholder="请输入验证码" required="true"><img class="imgCode" alt="点击图片刷新!" src="/common/kaptcha" onclick="this.src='/common/kaptcha?d='+new Date()*1">
</div>
说明:
- 就是准备了一个input输入框,供我们输入验证码;准备一个图片,显示我们的验证码
- 重点要说的就是照片img标签中,src的路径是一个URL,也就是说,这张照片的来源就是从这个URL来的;点击照片时,会触发onclick事件,这个事件会改变该图片src的属性,新的src为:'/common/kaptcha?d='new Date()*1,这个表达式会生成一个新的日期时间戳,并将其附加到图片的URL后面,从而获取一个新的图片~ 【src中的URL由后端实现~】
1.3、后端核心代码
准备一个controller类:
package com.example.demo.controller;import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Controller
@RequestMapping("/common")
public class commonCotroller {@GetMapping("/kaptcha")public void defaultKaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {httpServletResponse.setHeader("Cache-Control", "no-store");httpServletResponse.setHeader("Pragma", "no-cache");httpServletResponse.setDateHeader("Expires", 0);httpServletResponse.setContentType("image/gif");// 三个参数分别为宽、高、位数SpecCaptcha captcha = new SpecCaptcha(150, 30, 4);// 设置字体captcha.setCharType(Captcha.FONT_9);// 验证码存入sessionhttpServletRequest.getSession().setAttribute("authCode", captcha.text().toLowerCase());// 输出图片流captcha.out(httpServletResponse.getOutputStream());}
}
说明:
到这里,验证码的模块就实现完成了,具体,在登录时如何操作的,下面第四点中会举例说明~
2、账户冻结
2.1、思路:
关于账户冻结,我是在数据库设计中,给用户表添加了两个字段:状态state和冷却时间lTime。默认的state值为1,默认的lTime为0。当用户每登录错误一次时,给该用户的state加一;当state大于3时,表示该用户已经连续错误登录三次了,该账户将被冻结;冻结时间设置:获取现在的时间戳加上30000,换算成秒就是,给当前时间加上30s;在登录前,先验证给账户是否被冻结了,也就是查看当前时间戳是否小于该用户数据库中存储的冻结时间戳~
2.2、核心代码示例:
@RequestMapping("/login")public AjaxResult login(HttpServletRequest request, String username, String password,String authCode) {//0.参数校验if(!StringUtils.hasLength(username) || username.length() > 50) {return AjaxResult.fail("用户名输入违法,请重新输入!");}if(!StringUtils.hasLength(password) ||password.length() > 10) {return AjaxResult.fail("密码输入违法,请重新输入!");}if(!StringUtils.hasLength(authCode)) {return AjaxResult.fail("验证码不能为空!");}//1、校验验证码是否正确相关操作// ...//2、验证该用户的登录功能是否被冻结//2.1、先根据用户名查询出数据中的username的信息Userinfo userinfo = userService.getUserExist(username);if(userinfo == null) {return AjaxResult.fail("用户名或密码错误,请重新输入~");}//2.2、查看该用户的登录功能是否被冻结了if(userinfo.getState() > 3 && userinfo.getLTime() > System.currentTimeMillis()) {return AjaxResult.fail("登录已锁定,请等待" + (userinfo.getLTime() - System.currentTimeMillis())/1000 + "秒后重试");} else if(userinfo.getState() > 3 && userinfo.getLTime() < System.currentTimeMillis()) {//放置state为1--时间过了,解除冻结userinfo.setState(1);userService.stateOne(userinfo);}//3、对比密码是否正确相关操作// ...//3.3、可以正确登录,将之间的state标记恢复原状userinfo.setState(1);userService.stateOne(userinfo);//4、可以正确登录,后续操作// ....return AjaxResult.success("登陆成功");}
上述代码还是很好理解的,我就不做过多解释了~
3、密码加密——加盐算法
我们准备一个类,这个类主要就是处理密码的加密和验证密码操作。
3.1、思路:
- 1:我们使用UUID生成一个随机盐值;
- 2:密码加工1:把密码和盐值加起来,然后使用MD5哈希算法进行加密
- 3:密码加工2:为了后续可以取出盐值,从而来验证密码是否正确,所以最终的密码:盐值 + "$" + 密码加工1 【这里是以字符串的形式拼接的】
- 4:密码验证:先通过$符,取出盐值,再通过相同的加密方式加密,验证新密码加密后的值是否与数据库中的值相等~
3.2、代码实现示例:
public class PasswordUtils {//密码加盐:public static String encrypt(String password) {//1、生成一个32位的盐值String salt = UUID.randomUUID().toString().replace("-","");//2、生成加盐后的密码,并将盐值和加盐后的密码并在一起return splicing(password,salt);}//验证密码是否正确public static boolean check(String inputPassword,String finPassword) {//1、获取saltString salt = finPassword.split("\\$")[0];//2、使用一样的盐值,加密String inputFinPassword = splicing(inputPassword,salt);if(inputFinPassword.equals(finPassword)) {return true;}return false;}//密码加盐的辅助方法private static String splicing(String password, String salt) {//1、使用md5生成加盐后的密码1String finpassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());//2、返回最终密码【盐值 $ 密码1】return (salt + "$" +finpassword);}
}
4、小结:展示我的项目
上述重复的代码,我就不展示了,展示一下,我的UserController类的实现吧~
4.1、后端代码:
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/login")public AjaxResult login(HttpServletRequest request, String username, String password,String authCode) {//0.参数校验if(!StringUtils.hasLength(username) || username.length() > 50) {return AjaxResult.fail("用户名输入违法,请重新输入!");}if(!StringUtils.hasLength(password) ||password.length() > 10) {return AjaxResult.fail("密码输入违法,请重新输入!");}if(!StringUtils.hasLength(authCode)) {return AjaxResult.fail("验证码不能为空!");}//1、校验验证码是否正确HttpSession session = request.getSession();//默认为true,有则获取,无则会先新建再获取String trueAuthCode = (String) session.getAttribute("authCode");if(!trueAuthCode.equalsIgnoreCase(authCode)) {return AjaxResult.fail("验证码输入错误!");}//2、验证该用户的登录功能是否被冻结//2.1、先根据用户名查询出数据中的username的信息Userinfo userinfo = userService.getUserExist(username);if(userinfo == null) {return AjaxResult.fail("用户名或密码错误,请重新输入~");}//2.2、查看该用户的登录功能是否被冻结了if(userinfo.getState() > 3 && userinfo.getLTime() > System.currentTimeMillis()) {return AjaxResult.fail("登录已锁定,请等待" + (userinfo.getLTime() - System.currentTimeMillis())/1000 + "秒后重试");} else if(userinfo.getState() > 3 && userinfo.getLTime() < System.currentTimeMillis()) {//放置state为1--时间过了,解除冻结userinfo.setState(1);userService.stateOne(userinfo);}//3、对比密码是否正确if(!PasswordUtils.check(password,userinfo.getPassword())) {//3.1、如果密码错误,则数据库中标记+1userinfo.setState(userinfo.getState() + 1);//给数据库中的state+1userService.stateOne(userinfo);//3.2、错误次数达标,设置冷却时间if(userinfo.getState() > 3) {userinfo.setLTime(System.currentTimeMillis() + 30000);userService.setLTime(userinfo);}return AjaxResult.fail("用户名或密码错误,请重新输入~");}//3.3、可以正确登录,将之间的标记恢复原状userinfo.setState(1);userService.stateOne(userinfo);//4、可以正确登录,给session中存储给用户的信息-放置session信息session.setAttribute(AppVariable.USER_SESSION_KEY,userinfo);//5、返回登陆成功return AjaxResult.success("登陆成功");}
}
前端代码,我就不展示了~ 大家自行发挥~~~
4.2、效果展示:
好啦,本期就到这里咯,对效果展示中的弹窗感兴趣的伙伴,可以看看持续关注我后续的动态,会出一个简单的教程
相关文章:

OJ项目【登录】——验证码、失败登录多次账户冻结、用户密码加密,我是如何实现的?
目录 前言 1、验证码 1.1、引入pom 1.2、前端核心代码 1.3、后端核心代码 2、账户冻结 2.1、思路: 2.2、核心代码示例: 3、密码加密——加盐算法 3.1、思路: 3.2、代码实现示例: 4、小结:展示我的项目 4…...

js鼠标点击添加图标并获取图标的坐标值
给这个图片添加摄像头图标,并获取图标的坐标值,也就是图标的css样式是positon:absolute,获取left和top的值。 图片1 思路是这样的,获取这里的长度, 图片2 1.鼠标点击时距浏览器的左边距离和上边距离,相当于(0,0)坐标 …...

How to add a jar to a project in eclipse?
Project -> Properties -> Java Build Path -> Libraries -> Add External JARs...

动手实现H5仿原生app前进后退切换效果
动手实现H5仿原生app前进后退切换效果 前言 最近在优化H5页面,我注意到当开发完成的移动端H5页面嵌入到微信小程序或者原生app中时,当触发页面路由切换会与原生app看上去有点格格不入,因为H5页面<router-view>切换路由时是直接替换了…...

【标准化封装 SOT系列 】 D SOT-323 SOT-363
〇、关键词 SC70 。 一、D部分 SOT-323 SOT-363 这个应该叫SC-70可能更合适,典型特征 pin 间距 0.65mm ; body size 2.0mm1.25mm 这一节很像SOT-23,即A部分,因此也是最容易被混淆的。 二、SC70-3 / -5/ -6 鉴于此,封装最好给…...

软件测试肖sir__python之ui自动化实战和讲解03
python之ui自动化实战和讲解...

Kafka序列化反序列化解析、kafka schema
Kafka序列化反序列化解析、kafka schema。 kafka有自己的rpc协议,即nio bytebuf中的数据格式,详见之前的kafka相关介绍的文章。这里我们来看一下大家常用,有时又疑惑的序列化反序列化,对应rpc协议中的records,kafka叫Serdes,实际上也是字面上的意思serialize and deseri…...

谷歌浏览器中如何审查隐藏的元素
谷歌浏览器中如何审查隐藏的元素 方法1: 打开控制台 先鼠标移上先显示出来 快捷键按 CtrlShiftC,只能简单查看宽高,做不到复杂的的样式查询 方法2: 在控制台输入一个以下代码, 并保留光标在控制台闪烁,鼠标移上去显示…...

【vue】使用less报错:显示this.getOptions is not a function
在vue-cli中使用 lang“less” 时报错: Module build failed: TypeError: this.getOptions is not a function at Object.lessLoader 原因:版本过高所致,所用版本为 解决:降低版本:npm install less-loader4.1.0 --s…...

代码随想录第48天 | ● 739. 每日温度 ● 496.下一个更大元素 I
739. 每日温度 /*** param {number[]} temperatures* return {number[]}*/ var dailyTemperatures function(temperatures) {const ntemperatures.lengthconst resArray(n).fill(0)const stack[] // 递增栈:用于存储元素右面第一个比他大的元素下标stack.push(0…...

团购页面.
<!DOCTYPE html> <html><head><title>团购</title><meta http-equiv"content-type" content"text/html; charsetutf-8"/><meta name"apple-mobile-web-app-capable" content"yes"/><lin…...

linux-系统日志/var/log/简介
日志在排查文件的时候至关重要,在Linux上一般跟系统相关的日志默认都会放到/var/log下面。 1、/var/log/boot.log 一般包含系统启动时的日志,包括自启动的服务。 2、/var/log/btmp 记录所有失败登录信息。非文本文件,可以使用last -f /va…...

2022最新版-李宏毅机器学习深度学习课程-P26RNN-2
一、RNN网络结构 与时间有关的反向传播(每次不同) 损失函数 实验其实不容易跑,因为他的损失函数曲线幅度很大 画出来差不多是这个样子。突然一下升高是因为从右到左碰到陡峭的地方梯度一下变大了,所以弹回去了。 原作者在训练时…...

docker 配置mongoDB
## 拉取镜像 docker pull mongo## 设置默认账号密码 test:test 默认数据 test docker run -d --name mongo-container -e MONGO_INITDB_ROOT_USERNAMEtest -e MONGO_INITDB_ROOT_PASSWORDtest -e MONGO_INITDB_DATABASEtest -p 27017:27017 mongo...

基于PHP的宠物爱好者交流平台管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…...

盘点数据采集中14种常见的反爬策略
引言 随着互联网的飞速发展, 爬虫技术不断演进, 为数据获取和信息处理提供了强大支持。然而, 滥用爬虫和恶意爬取数据的行为日益增多, 引发了反爬虫技术的兴起。在这场看似永无止境的 技术较量 中, 爬虫与反爬虫技术相互博弈、角力。本文将简单过下目前已知的几种反爬策略, 旨…...

直播预告:防御升级-SMC2精准对抗账号劫持和漏洞威胁
当邮箱账号出现疑似被盗风险和遭受外部攻击时,企业管理员需要尽快发现或排除潜在威胁,并采取处置措施,阻止威胁扩大。 那么面对账号失陷风险,企业管理员如何做到账号异常行为的精准检测和即时处置?当账号遭受外部攻击时…...

班主任好物 班级查询系统来啦
哈喽各位,作为一名教育博主,今天我要给大家分享一个班主任的好物——班级查询系统!这个系统可真是太方便了呢,那么,这个神秘的班级查询系统到底是什么呢?别急,听我慢慢道来。 班级查询系统&…...

【性能测试】使用JMeter对code论坛进行压力测试
1.项目介绍 项目简介 code 论坛是一个技术交流社区。主要功能有发布帖子,查看帖子,评价帖子,删除帖子,点赞帖子,站内信,个人中心,修改个人信息等。是一个基于 Spring 的前后端分离项目。 项目链…...

Windows 事件日志监控
Windows 事件日志是记录 Microsoft 系统上发生的所有活动的文件,在 Windows 环境中,将记录系统上托管的系统、安全性和应用程序的事件,事件日志提供包含有关事件的详细信息,包括日期、时间、事件 ID、源、事件类型和发起它的用户。…...

pytorch里常用操作(持续更新)
对不起我脑子不太记事儿每次变换都得想想想所以干脆汇总一下算了,当然也有一些不是torch包里面的但是没有关系hhh 官方文档里有一堆不太常用的,这里整理的都是自己比较常用的 张量操作 torch.tensor:从Python列表或NumPy数组创建张量 torc…...

地铁大数据客流分析系统 设计与实现 计算机竞赛
文章目录 1 前言1.1 实现目的 2 数据集2.2 数据集概况2.3 数据字段 3 实现效果3.1 地铁数据整体概况3.2 平均指标3.3 地铁2018年9月开通运营的线路3.4 客流量相关统计3.4.1 线路客流量排行3.4.2 站点客流量排行3.4.3 入站客流排行3.4.4 整体客流随时间变化趋势3.4.5 不同线路客…...

00后都到适婚年龄啦!90后的还在低调什么?
当你的想法还停留在00后读书时代,其实大部分00后早已步入工作社会,还有不少人已经步入婚姻。广东金媒人婚恋,无论是广州、深圳、东莞、佛山举办活动的参与者中,00后的男生女生都占了不少。 广州深圳这样一二线城市的单身年轻人群&…...

reactnative使用七牛云上传图片
安装react-native-qiniu npm install react-native-qiniu --save 上传文件 import Qiniu,{Auth,ImgOps,Conf,Rs,Rpc} from react-native-qiniu;// 初始化七牛云配置 // Qiniu.region.z0:华东地区(默认值)。 // Qiniu.region.z1:…...

在JavaScript中,如何创建一个数组或对象?
在JavaScript中,可以使用以下方式创建数组和对象: 一:创建数组(Array): 1:使用数组字面量(Array Literal)语法,使用方括号 [] 包裹元素,并用逗号分隔: let array1 = []; // 空数组 let array2 = [1, 2, 3]; // 包含三个数字的数组 let array3 = [apple, banana,…...

001.第一个C语言项目
Visual studio2022的使用 创建第一个C语言项目和源文件 https://blog.csdn.net/qq_45037165/article/details/124520286 第一个C语言项目 #include<stdio.h> int main() {printf("Hello World");return 0; }运行结果: 第一行为库函数࿰…...

luffy项目后端轮播图接口
后台主页功能 需求 根据原型图,分析出首页需要配合俩接口 轮播图接口(要写) 查询所有轮播图 推荐课程接口(暂时先不写) 设计表 轮播图表:Banner 写轮播图接口 查询所有轮播图 轮播图表 写一个公共表模型且只用于继承 fr…...

如何通过Photoshop将视频转换成GIF图片
一、应用场景 1、将视频转有趣动图发朋友圈 2、写CSDN无法上传视频,而可以用GIF动图替代 3、其他 二、实现步骤 1、打开Photoshop APP 2、点击文件——导入——视频帧到图层 3、选择视频文件 4、配置视频信息,按照图片提示配置完毕之后点击确定&…...

书单|1024程序员狂欢节充能书单!
点击链接进入图书专题 1024程序员节 “IT有得聊”是机械工业出版社旗下IT专业资讯和服务平台,致力于帮助读者在广义的IT领域里,掌握更专业、更实用的知识与技能,快速提升职场竞争力。 点击蓝色微信名可快速关注我们。 一年一度的1024程序员…...

GRS认证与TC交易证明的区别
TC(Transaction Certificate)交易证书是由认证单位向其客户出具再生含量证明,证明本次 销售产品符合GRS标准。TC交易证书上列明 卖方(seller),买方(buyer),收货方 (consi…...