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、源、事件类型和发起它的用户。…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇
根据 QYResearch 发布的市场报告显示,全球市场规模预计在 2031 年达到 9848 万美元,2025 - 2031 年期间年复合增长率(CAGR)为 3.7%。在竞争格局上,市场集中度较高,2024 年全球前十强厂商占据约 74.0% 的市场…...
