OJ项目【登录】——验证码、失败登录多次账户冻结、用户密码加密,我是如何实现的?

news2024/11/20 23:26:52

目录

前言

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);

        // 验证码存入session
        httpServletRequest.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、获取salt
        String 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生成加盐后的密码1
        String finpassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
        //2、返回最终密码【盐值 $ 密码1】
        return (salt + "$" +finpassword);
    }
}

4、小结:展示我的项目

        上述重复的代码,我就不展示了,展示一下,我的UserController类的实现吧~

4.1、后端代码:

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private 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、如果密码错误,则数据库中标记+1
            userinfo.setState(userinfo.getState() + 1);
            //给数据库中的state+1
            userService.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、效果展示:

 

        好啦,本期就到这里咯,对效果展示中的弹窗感兴趣的伙伴,可以看看持续关注我后续的动态,会出一个简单的教程 

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

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

相关文章

[牛客习题]“幸运的袋子”

习题链接&#xff1a;幸运的袋子_牛客题霸_牛客网 题目分析 由题意可知&#xff1a;“幸运的袋子”的概念是——小球的数值之和大于小球的数值之积。 假如现在有5个小球&#xff1a;1&#xff0c;1&#xff0c;3&#xff0c;5&#xff0c;7&#xff0c;并将他们编号a0~a4.我们…

Vue项目路由加前缀

Vue项目路由加前缀 vue-cli3.0配置 1&#xff09;静态资源前缀 vue.config.js /module.exports 配置 publicPath&#xff1a;“/前缀” 2&#xff09;路由前缀 route/index.js export default new Router({ base:”/前缀" , }) 参考文章&#xff1a;https://blog.csd…

【Java学习之道】网络编程的基本概念

引言 这一章我们将一同进入网络编程的世界。在开始学习网络编程之前&#xff0c;我们需要先了解一些基本概念。那么&#xff0c;我们就从“什么是网络编程”这个问题开始吧。 一、网络编程的基本概念 1.1 什么是网络编程 网络编程&#xff0c;顾名思义&#xff0c;就是利用…

netca_crypto.dll找不到怎么修复?详细解决办法和注意事项

当你在使用计算机时&#xff0c;突然出现了一个错误提示&#xff1a;“netca_crypto.dll 找不到”。不知道该如何解决这个问题&#xff1f;其实要解决是非常的简单的&#xff0c;今天我们将为你提供几种修复 netca_crypto.dll 找不到的解决方法和一些注意事项。在深入探讨修复方…

普通螺纹基本牙型尺寸及拧紧力矩.exe

一、概要 本软件功能主要是通过输入螺纹原始三角形高度P,螺栓规格(公称直径)d,材料的屈服应力σs,计算出公称应力截面积As、外螺纹小径d1、外螺纹小径d2、拧紧力矩T等参数。 开发本软件的原因主要有以下几点: 提高设计效率:通过这款软件,工程师可以快速计算螺纹的基本牙…

转行网络安全是否可行?

一、前言 其实很多的IT大佬之前也不是专门学计算机的&#xff0c;都是后期转行的。而且大学学什么专业&#xff0c;对后期的工作真的没有太大关系&#xff0c;这也是现在高校的教育现状。有80%的学生都是通过临时抱佛脚&#xff0c;考前冲刺拿到毕业证书的。下面就带大家详细分…

2023年淘宝天猫双11红包领取活时间什么时候开始领天猫淘宝双十一红包优惠券?

2023年淘宝天猫双11红包领取活动开始与结束时间 2023年10月24日20:00开始领取至11月11日23:59结束&#xff1b; 2023年淘宝天猫双11红包活动使用开始与结束时间 第一波&#xff1a;2023年10月31日20:00开始使用至11月3日23:59 第二波&#xff1a;2023年11月10日20:00开始使用…

服务安全-应用协议rsync未授权ssh漏洞复现

目录 服务攻防-应用协议rsync&ssh漏洞复现漏洞复现配置不当-未授权访问-rsync文件备份OpenSSH 用户名枚举漏洞libssh身份验证绕过漏洞 服务攻防-应用协议rsync&ssh漏洞复现 漏洞复现 配置不当-未授权访问-rsync文件备份 rsync默认端口&#xff1a;873 rsync是Linux下…

代码随想录Day20 回溯算法 LeetCode77 组合问题

以下内容更详细解释来自于:代码随想录 (programmercarl.com) 1.回溯算法理论基础 回溯法也叫回溯搜索法,是搜索法的一种,我们之前在二叉树中也经常使用到回溯来解决问题,其实有递归就有回溯,有的时候回溯隐藏在递归之下,我们不容易发觉,今天我们来详细介绍一下什么是回溯,它能…

深圳寄包裹到德国

深圳&#xff0c;作为全球最发达的城市之一&#xff0c;以其高效的物流服务在全球范围内享有盛名。如果你正在寻找一种方式将包裹从深圳寄送到德国&#xff0c;那么本文将为你提供详细的步骤和建议。 第一步&#xff1a;了解国际邮寄的基本信息 首先&#xff0c;你需要了解包裹…

10.16课上

煎饼排序 第一步找剩余数组里的最大值&#xff0c;然后从头到这里翻转一次&#xff0c;这样最大值就到了开头&#xff0c;再把开头从当前结尾翻转一次&#xff0c;就把当前的最大值翻转到了最后 class Solution { public:vector<int> pancakeSort(vector<int>&am…

吃瓜教程-模型的评估与选择

在训练集上的误差称为训练误差&#xff08;training error&#xff09;或经验误差&#xff08;empirical error&#xff09;。在测试集上的误差称为测试误差&#xff08;test error&#xff09;。学习器在所有新样本上的误差称为泛化误差&#xff08;generalization error&…

Apipost一键压测已支持导入CSV文件

最近更新中Apipost对UI页面进行了一些调整&#xff0c;另外一键压测功能支持参数化&#xff01;本篇文章将详细介绍这些改动&#xff01; API调试页面的细节改动 在请求区填入请求参数或脚本时会有相应的标识 如在Query中填入多个参数时上方会展示数量 在预、后执行脚本中写…

Vue3.0 项目结构及组件

main.js文件 // vue中main.js的作用 // main.js是项目的入口文件&#xff0c;项目中所有的页面都会加载main.js,所以main.js,主要有三个作用&#xff1a; // 1.实例化Vue。 // 2.放置项目中经常会用到的插件和CSS样式。例如&#xff1a; 网络请求插件:axios和vue-resource、图…

vue小写数字转大写-例如:11转为十一

vue小写数字转大写-例如&#xff1a;11转为十一 在Vue中&#xff0c;可以使用自定义过滤器&#xff08;Custom Filter&#xff09;来将数字转换为大写的形式。 下面是一个示例&#xff1a; // main.js import Vue from vue;Vue.filter(toChineseNumber, function (value) {c…

2.3 初探Hadoop世界

文章目录 零、学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;Hadoop的前世今生1、Google处理大数据三大技术2、Hadoop如何诞生3、Hadoop主要发展历程 &#xff08;二&#xff09;Hadoop的优势1、扩容能力强2、成本低3、高效率4、可靠性5、高容错性 &#xff08;三…

Bitquiz重塑Learn to Earn热潮,用户零投入让学习创造价值

Axie 带来的暴富效应、StepN 带来的出圈效应&#xff0c;近期Bigtime 在熊市中的大火&#xff0c;为加密参与者带来的赚取效应&#xff0c;X to Earn 重新成为整个市场关注的重点&#xff0c;GameFi 再次站在了风口浪尖。 大家开始寻找下一个Bigtime&#xff0c;希望能够抓住一…

设计模式_迭代器模式

迭代器模式 介绍 设计模式定义案例迭代器模式行为型&#xff1a;关注对象与行为的分离 提供了一种统一的方式来访问多个不同的集合两个集合&#xff1a;使用了不同的数据存储方式 学生 和 警察 查询显示出集合的内容 &#xff0c;使用相同的代码 问题堆积在哪里解决办法不同…

在IE浏览器下fixed定位容器随着滚动条出现抖动问题(实测有效)

在ie浏览器下使用fixed定位的容器随着滚动条滚动出现晃动&#xff0c;这种问题比较常见&#xff0c;以下我们给两个解决方案。 方案一 把滑动滚动取消 方案二 在vue组件的created生命周期中添加此代码 document.addEventListener(wheel,function(event) {event.preventDefa…

大模型引发“暴力计算”,巨头加速推进液冷“降温”

点击关注 文&#xff5c;姚悦 编&#xff5c;王一粟 一进入部署了液冷服务器的数据中心&#xff0c;不仅没有嘈杂的风扇声&#xff0c;甚至在不开空调的夏日也完全没有闷热感。 在大模型引发“暴力计算”的热潮下&#xff0c;数据中心的上下游&#xff0c;正在加紧推进液冷“…