投票项目_登录功能的版本迭代

V0版本:

        实现最简单的登录,写个接口去数据库查有没有前端传来的账号和密码,查到且密码正确返回“登录成功”,其余情况统一返回“账号或密码错误”。

V1版本:

        用session代替cookie 先导入依赖,将session加入到redis中

        1.导入依赖

        

        <dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-core</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency>

        2. 设置拦截器

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String requestURI = request.getRequestURI();log.info("拦截到请求requestURI:{}", requestURI);// 这里可以使用false来避免自动创建新的空会话HttpSession session = request.getSession();// 检查用户是否已登录if (session != null && session.getAttribute("userId") != null) {// 用户已登录log.info("用户已登录放行");return true;} else {// 用户未登录log.info("用户未登录,以跳转到登录页面");response.setStatus(401);response.sendRedirect("http://localhost:8080/login.html");return false; // 终止请求处理}}}import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") // 拦截所有//选择排除不需要拦截的地址.excludePathPatterns("/login","/login.html","/regist","/regist.html");}
}

        3. 给session加一个userId字段,用于拦截器的处理

        HttpSession session = request.getSession();session.setAttribute("userId", dbUser.getId());System.out.println("Session中创建的userId:" + session.getAttribute("userId"));

V2版本:

        对前端传来的密码进行加盐和加密处理

        String password = loginDTO.getPassword();String userSalt = dbUser.getSalt();String DBpassword = dbUser.getPassword();String saltPassword = password+userSalt;String md5SaltPwd = DigestUtils.md5DigestAsHex(saltPassword.getBytes());if(!md5SaltPwd.equals(DBpassword)){return  R.error("用户名或者密码错误");}

V3版本:

        1. 生成验证码的工具类

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import javax.imageio.ImageIO;import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.Random;public class ValidateCodeUtil {private static Random random = new Random();private int width = 165; //验证码的宽private int height = 45; //验证码的高private int lineSize = 30; //验证码中夹杂的干扰线数量private int randomStrNum = 4; //验证码字符个数private String randomString = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ";private final String sessionKey = "JCCODE";//字体的设置private Font getFont() {return new Font("Times New Roman", Font.ROMAN_BASELINE, 40);}//颜色的设置private static Color getRandomColor(int fc, int bc) {fc = Math.min(fc, 255);bc = Math.min(bc, 255);int r = fc + random.nextInt(bc - fc - 16);int g = fc + random.nextInt(bc - fc - 14);int b = fc + random.nextInt(bc - fc - 12);return new Color(r, g, b);}//干扰线的绘制private void drawLine(Graphics g) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(20);int yl = random.nextInt(10);g.drawLine(x, y, x + xl, y + yl);}//随机字符的获取private  String getRandomString(int num){num = num > 0 ? num : randomString.length();return String.valueOf(randomString.charAt(random.nextInt(num)));}//字符串的绘制private String drawString(Graphics g, String randomStr, int i) {g.setFont(getFont());g.setColor(getRandomColor(108, 190));//System.out.println(random.nextInt(randomString.length()));String rand = getRandomString(random.nextInt(randomString.length()));randomStr += rand;g.translate(random.nextInt(3), random.nextInt(6));g.drawString(rand, 40 * i + 10, 25);return randomStr;}//生成随机图片public void getRandomCodeImage(HttpServletRequest request, HttpServletResponse response){HttpSession session = request.getSession();// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);Graphics g = image.getGraphics();g.fillRect(0, 0, width, height);g.setColor(getRandomColor(105, 189));g.setFont(getFont());// 干扰线for (int i = 0; i < lineSize; i++) {drawLine(g);}// 随机字符String randomStr = "";for (int i = 0; i < randomStrNum; i++) {randomStr = drawString(g, randomStr, i);}System.out.println("随机字符:"+randomStr);g.dispose();//移除之前的session中的验证码信息session.removeAttribute(sessionKey);//重新将验证码放入sessionsession.setAttribute(sessionKey, randomStr);try {//  将图片以png格式返回,返回的是图片ImageIO.write(image, "PNG", response.getOutputStream());} catch (Exception e) {e.printStackTrace();}}//生成随机图片的base64编码字符串public String getRandomCodeBase64(HttpServletRequest request, HttpServletResponse response) {HttpSession session = request.getSession();// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);Graphics g = image.getGraphics();g.fillRect(0, 0, width, height);g.setColor(getRandomColor(105, 189));g.setFont(getFont());//干扰线for (int i = 0; i < lineSize; i++) {drawLine(g);}//随机字符String randomStr = "";for (int i = 0; i < randomStrNum; i++) {randomStr = drawString(g, randomStr, i);}System.out.println("随机字符:"+randomStr);g.dispose();session.removeAttribute(sessionKey);session.setAttribute(sessionKey, randomStr);String base64String = "";try {//  直接返回图片//  ImageIO.write(image, "PNG", response.getOutputStream());//返回 base64ByteArrayOutputStream bos = new ByteArrayOutputStream();ImageIO.write(image, "PNG", bos);byte[] bytes = bos.toByteArray();Base64.Encoder encoder = Base64.getEncoder();base64String = encoder.encodeToString(bytes);} catch (Exception e) {e.printStackTrace();}return base64String;}}

        2. 基于工具类的方法类

import com.example.votedemo.common.ValidateCodeUtil;
import com.google.common.util.concurrent.RateLimiter;
import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@RestController
public class ValidateCodeController {//返回验证码图片@GetMapping("/getCaptchaImg")public void getCaptchaImg(HttpServletRequest request, HttpServletResponse response, HttpSession session) {try {response.setContentType("image/png");response.setHeader("Cache-Control", "no-cache");response.setHeader("Expire", "0");response.setHeader("Pragma", "no-cache");ValidateCodeUtil validateCode = new ValidateCodeUtil();// getRandomCodeImage方法会直接将生成的验证码图片写入responsevalidateCode.getRandomCodeImage(request, response);// System.out.println("session里面存储的验证码为:"+session.getAttribute("JCCODE"));} catch (Exception e) {e.printStackTrace();}}// 验证码校验@GetMapping("/checkCaptcha")@ApiOperation("验证码校验接口")public boolean getCheckCaptcha(@RequestParam("code") String code, HttpSession session) {try {//toLowerCase() 不区分大小写进行验证码校验String sessionCode= String.valueOf(session.getAttribute("JCCODE")).toLowerCase();System.out.println("session里的验证码:"+sessionCode);String receivedCode=code.toLowerCase();System.out.println("用户的验证码:"+receivedCode);return !sessionCode.equals("") && !receivedCode.equals("") && sessionCode.equals(receivedCode);} catch (Exception e) {return false;}}// 例如,创建一个每秒允许生成1个验证码的限流器RateLimiter rateLimiter = RateLimiter.create(1.0); // 参数表示每秒令牌生成速率// 生成验证码,返回的是 base64@GetMapping("/getCaptchaBase64")@ApiOperation("返回base64验证码接口")public Object getCaptchaBase64(HttpServletRequest request, HttpServletResponse response) {if (!rateLimiter.tryAcquire()) {// 如果获取令牌失败(即超过限流阈值)Map<String, String> result = new HashMap<>();result.put("message", "请求过于频繁,请稍后再试");return result;}Map result = new HashMap();try {response.setContentType("image/png");response.setHeader("Cache-Control", "no-cache");response.setHeader("Expire", "0");response.setHeader("Pragma", "no-cache");ValidateCodeUtil validateCode = new ValidateCodeUtil();// 返回base64String base64String = validateCode.getRandomCodeBase64(request, response);result.put("url", "data:image/png;base64," + base64String);result.put("message", "created successfull");//http://tool.chinaz.com/tools/imgtobase/  base64直接转为图片网站System.out.println("结果:" + result.get("url"));} catch (Exception e) {System.out.println(e);}return result;}}

        3. 功能使用

    @AutowiredValidateCodeController validateCodeController;@PostMapping("/login")@Transactional@ApiOperation("用户登录接口")public R<String> login(@RequestBody LoginDTO loginDTO, HttpServletRequest request){// 登录// 先进行验证码校验boolean captchaVerified = validateCodeController.getCheckCaptcha(loginDTO.getCaptcha(), request.getSession());if (!captchaVerified) {return R.error("验证码错误");}......

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

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

相关文章

智慧园区可视化的价值,不要再吐槽没啥用了。

2023-04-20 13:30贝格前端工场 提高园区运营效率&#xff1a;智慧园区可以通过物联网技术、大数据分析等手段&#xff0c;实现对园区内设施、设备、人员等的实时监控和管理&#xff0c;从而提高园区的运营效率&#xff0c;降低管理成本。 提升园区服务水平&#xff1a;智慧园区…

前端Vue项目无法启动服务,提示无 ‘dev‘ npm的脚本问题解决

目录 一、问题详情 二、问题解决 一、问题详情 上周还能运行的项目&#xff0c;今天突然无法执行了&#xff0c;连最基本的启动按钮也没有了&#xff0c;所有的项目本地都突然跑不起来了&#xff0c;附上截图。 二、问题解决 后来排查的根本原因有点奇葩&#xff0c;是因为…

C++面试 -操作系统-安全能力:死锁的危害、出现原因、解决方法

目录 死锁的危害 死锁出现的原因 死锁的解决方法 死锁是计算机科学中一个非常重要的概念&#xff0c;特别是在多线程、并发编程以及数据库管理系统等领域中。下面是关于死锁的危害、出现原因和解决方法的基础概述&#xff1a; 死锁的危害 资源浪费&#xff1a;死锁导致系统…

ABBYY FineReader16文档转换、PDF管理与文档比较功能介绍

ABBYY FineReader 16作为一款OCR和PDF一体化程序&#xff0c;其强大的功能使得文档处理变得简单高效。在众多功能中&#xff0c;文档转换、PDF管理和文档比较这三大功能尤为突出&#xff0c;成为了众多企业和个人用户的首选工具。 ABBYY Finereader 16-安装包下载如下&#xff…

【每日前端面经】2023-02-26

题目来源: 牛客 http和https http是一种用于分布式、协作式和超媒体信息系统的应用层协议。简单来说就是一种发布和接收HTML页面的方法&#xff0c;被用于在Web浏览器和网站服务器之间传递消息。该协议以明文方式发送内容&#xff0c;不提供任何方式的数据加密&#xff0c;如…

内存函数(C语言进阶)

目录 前言 1、memcpy 2、memmove 3、memcmp 4、memset 结语 前言 本篇介绍了C语言中的内存函数&#xff0c;内存函数&#xff0c;顾名思义就是处理内存的函数。 1、memcpy memcpy&#xff1a;内存拷贝函数。 相对于strcpy只能拷贝字符串来讲&#xff0c;memcpy能拷…

Qt介绍以及qt_creater的安装和C++项目工程创建

最近天气严寒&#xff0c;同学们要注意保暖哦&#xff01;学习的同时别忘了照顾好自己呀&#xff01;o(*&#xffe3;▽&#xffe3;*)ブ 目录 一、Qt 1、Qt概念 2、常见的GUI 二、安装qt_creater 方法一&#xff1a; 方法二&#xff1a; 三、Qt_creater 中C项目的创建 …

MySQL之sql函数分类

华子目录 sql函数聚合函数数值型函数字符串函数日期和时间函数流程控制函数case用法 sql函数 聚合函数 聚合函数是对一组值进行运算&#xff0c;并返回单个值。也叫分组函数&#xff0c;具体用法请参考该博文 https://blog.csdn.net/huaz_md/article/details/136081708?spm1…

MATLAB环境下一种改进的瞬时频率(IF)估计方法

相对于频率成分单一、周期性强的平稳信号来说&#xff0c;具有非平稳、非周期、非可积特性的非平稳信号更普遍地存在于自然界中。调频信号作为非平稳信号的一种&#xff0c;由于其频率时变、距离分辨率高、截获率低等特性&#xff0c;被广泛应用于雷达、地震勘测等领域。调频信…

PostgreSQL内存上下文系统设计概述

PostgreSQL内存上下文系统设计概述 原文:src/backend/utils/mmgr/README 背景 我们在“内存上下文”中进行大部分内存分配&#xff0c;通常是AllocSets由src/backend/utils/mmgr/aset.c实现。在没有大量开销的情况下成功进行内存管理的关键是定义一组具有适当生命周期的有用…

华为大数据平台-FusionInsight MRS

1、产品定位 (1) 关于华为的大数据平台&#xff0c;本人之前用过FusionInsight HD版本&#xff0c;近期也在用MRS结合MPP和治理平台做湖仓一体的开发&#xff0c;其实MRS是在HD基础上进行的升级、改版&#xff0c;MRS是集成一些开源的大数据组件&#xff0c;有自己的运维和安全…

【leetcode】剑指Offer专项突击版含注释 Java版本(一)

目录 前言第一天&#xff08;整数&#xff09;剑指 Offer II 002. 二进制加法&#xff08;简单&#xff09; 第二天&#xff08;整数&#xff09;剑指 Offer II 004. 只出现一次的数字 &#xff08;中等&#xff09;剑指 Offer II 005. 单词长度的最大乘积&#xff08;中等&…

LabVIEW光伏逆变器低电压穿越能力测试

LabVIEW光伏逆变器低电压穿越能力测试 随着光伏发电技术的迅速发展&#xff0c;光伏逆变器的低电压穿越&#xff08;LVRT&#xff09;能力日益成为影响电网稳定性的关键因素。为了提升光伏逆变器的并网性能&#xff0c;开发了一套基于LabVIEW的光伏逆变器LVRT测试系统。该系统…

如何成为fpga工程师

FPGA的应用领域非常的广&#xff0c;尤其再人工智能&#xff0c;大数据&#xff0c;云计算等等方向非常吃香。加上国家这两年的政策支持&#xff0c;整个芯片行业相比较其他的传统行业来说会好很多&#xff0c;总之前景是光明的&#xff0c;道路是曲折的&#xff0c;想要在人才…

05-验证整数输入

需求分析 我们在脚本中验证整数输入可谓是小菜一碟&#xff0c;但如果你也想接受负数的话&#xff0c;可就没那么容易了。问题在于每个数值只能有一个负号&#xff0c;而且还必须出现在数值的最开始部分。下面脚本可以确保正确地格式化负数&#xff0c;另外还能检查其值是否位…

Parquet 文件生成和读取

文章目录 一、什么是 Parquet二、实现 Java 读写 Parquet 的流程方式一&#xff1a;遇到的坑&#xff1a;坑1&#xff1a;ClassNotFoundException: com.fasterxml.jackson.annotation.JsonMerge坑2&#xff1a;No FileSystem for scheme "file"坑3&#xff1a;与 spa…

JAVA工程师面试专题-《并发编程篇》

目录 一、线程 1、并发与并行的区别 2、同步和异步的区别 3、Java中创建线程有哪些方式? 4、Thread和Runnable的区别 5、Java中的Runnable、Callable、Future、FutureTask的区别和联系&#xff1f; 6、说一下你对 CompletableFuture 的理解 7、volatile关键字有什么用&…

Ansible script 模块 该模块用于将本机的脚本在被管理端的机器上运行。Ansible服务执行本机脚本

目录 过程首先&#xff0c;我们写一个脚本&#xff0c;并给其加上执行权限直接运行命令来实现在被管理端执行该脚本验证错误演示 过程 该模块直接指定脚本的路径即可 首先&#xff0c;我们写一个脚本&#xff0c;并给其加上执行权限 vim /tmp/df.sh编辑脚本内容 这个脚本内容…

信钰证券:无任何氢能产品形成收入,这只氢能概念股却八连板了

受氢能方针面影响&#xff0c;多个氢能股迎来连涨潮。 2月26日&#xff0c;蓝科高新(601798.SH)涨停&#xff0c;截至收盘报11.01元&#xff0c;涨幅9.99%&#xff0c;完成八连板&#xff0c;总市值39.03亿元。首要因其地点氢能板块全体上涨影响。 同日同花顺氢动力概念下&am…

PyTorch 的 Autograd Engine(自动求导引擎)

PyTorch 的 Autograd Engine&#xff08;自动求导引擎&#xff09;是 PyTorch 中实现自动求导功能的核心组件之一。Autograd Engine 负责构建计算图、跟踪张量操作&#xff0c;并自动计算梯度。以下是 Autograd Engine 的一些关键特点和功能&#xff1a; 动态计算图&#xff1a…