当前位置: 首页
科技数码
Springboot 分布式验证码登录的通用方案

Springboot 分布式验证码登录的通用方案

热心网友 时间:2025-09-05
转载

传统的项目大都是基于session交互的,前后端都在一个项目里面,比如传统的SSH项目或者一些JSP系统,当前端页面触发到获取验证码请求,可以将验证码里面的信息存在上下文中,所以登录的时候只需要 用户名、密码、验证码即可。

为了防止世界被破坏,为了守护世界的和平。。。说错了,重来~

为了防止验证系统被暴力破解,很多系统都增加了验证码效验,比较常见的就是图片二维码,业内比较安全的是短信验证码,当然还有一些拼图验证码,加入人工智能的二维码等等,我们今天的主题就是前后端分离的图片二维码登录方案。

前后端未分离的验证码登录方案

传统的项目大都是基于session交互的,前后端都在一个项目里面,比如传统的SSH项目或者一些JSP系统,当前端页面触发到获取验证码请求,可以将验证码里面的信息存在上下文中,所以登录的时候只需要用户名、密码、验证码即可。

验证码生成流程如下

图片图片

登录验证流程如下

图片图片

可以发现,整个登录流程还是依赖session上下文的,并且由后端调整页面。

前后端分离的验证码登录方案

随着系统和业务的不停升级,前后端代码放在一起的项目越来越臃肿,已经无法快速迭代和职责区分了,于是纷纷投入了前后端分离的怀抱,发现代码和职责分离以后,开发效率越来越高了,功能迭代还越来越快,但是以前的验证码登录方案就要更改了。

验证码生成流程如下

图片图片

对比原来的方案,增加了redis中间件,不再是存在session里面了,但是后面怎么区分这个验证码是这个请求生成的呢?所以我们加入了唯一标识符来区分

登录验证流程如下

图片图片

可以发现,基于前后端分离的分布式项目登录方案对比原来,加了一个redis中间件和token返回,不再依赖上下文session,并且页面调整也是由后端换到了前端

动手撸轮子

基于验证码的轮子还是挺多的,本文就以Kaptcha这个项目为例,通过springboot项目集成Kaptcha来实现验证码生成和登录方案。

Kaptcha介绍

Kaptcha是一个基于SimpleCaptcha的验证码开源项目;

我找的这个轮子是基于SimpleCaptcha二次封装的,maven依赖如下:

com.github.penggle kaptcha 2.3.2

新建项目并加入依赖

依赖主要有 SpringBoot、Kaptcha、Redis;

pom.xml

4.0.0 com.lzp kaptcha 1.0-SNAPSHOT

org.springframework.boot spring-boot-starter-parent 2.3.0.RELEASE com.github.penggle kaptcha 2.3.2 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-redis org.apache.commons commons-pool2 com.alibaba fastjson 1.2.3 com.fasterxml.jackson.core jackson-databind

org.springframework.boot spring-boot-maven-plugin

Redis配置类RedisConfig

@Configurationpublic class RedisConfig { @Bean public RedisTemplate redisTemplate(LettuceConnectionFactory redisConnectionFactory){ RedisTemplate redisTemplate = new RedisTemplate(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; }}

验证码配置类KaptchaConfig

@Configurationpublicclass KaptchaConfig { @Bean public DefaultKaptcha producer(){ DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); Properties properties = new Properties(); properties.setProperty("kaptcha.border", "no"); properties.setProperty("kaptcha.border.color", "105,179,90"); properties.setProperty("kaptcha.textproducer.font.color", "black"); properties.setProperty("kaptcha.image.width", "110"); properties.setProperty("kaptcha.image.height", "40"); properties.setProperty("kaptcha.textproducer.char.string","23456789abcdefghkmnpqrstuvwxyzABCDEFGHKMNPRSTUVWXYZ"); properties.setProperty("kaptcha.textproducer.font.size", "30"); properties.setProperty("kaptcha.textproducer.char.space","3"); properties.setProperty("kaptcha.session.key", "code"); properties.setProperty("kaptcha.textproducer.char.length", "4"); properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");// properties.setProperty("kaptcha.obscurificator.impl","com.xxx");可以重写实现类 properties.setProperty("kaptcha.noise.impl","com.google.code.kaptcha.impl.NoNoise"); Config config = new Config(properties); defaultKaptcha.setConfig(config); return defaultKaptcha; }

验证码控制层CaptchaController

为了方便代码写一块了,讲究看;

package com.lzp.kaptcha.controller;import com.google.code.kaptcha.impl.DefaultKaptcha;import com.lzp.kaptcha.service.CaptchaService;import com.lzp.kaptcha.vo.CaptchaVO;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import sun.misc.BASE64Encoder;import javax.imageio.ImageIO;import java.awt.image.BufferedImage;import java.io.ByteArrayOutputStream;import java.io.IOException;@RestController@RequestMapping("/captcha")publicclass CaptchaController { @Autowired private DefaultKaptcha producer; @Autowired private CaptchaService captchaService; @ResponseBody @GetMapping("/get") public CaptchaVO getCaptcha() throws IOException { // 生成文字验证码 String content = producer.createText(); // 生成图片验证码 ByteArrayOutputStream outputStream = null; BufferedImage image = producer.createImage(content); outputStream = new ByteArrayOutputStream(); ImageIO.write(image, "jpg", outputStream); // 对字节数组Base64编码 BASE64Encoder encoder = new BASE64Encoder(); String str = "data:image/jpeg;base64,"; String base64Img = str + encoder.encode(outputStream.toByteArray()).replace(" ", "").replace(" ", ""); CaptchaVO captchaVO =captchaService.cacheCaptcha(content); captchaVO.setBase64Img(base64Img); return captchaVO; }}

验证码返回对象CaptchaVO

package com.lzp.kaptcha.vo;publicclass CaptchaVO { /** * 验证码标识符 */ private String captchaKey; /** * 验证码过期时间 */ private Long expire; /** * base64字符串 */ private String base64Img; public String getCaptchaKey() { return captchaKey; } public void setCaptchaKey(String captchaKey) { this.captchaKey = captchaKey; } public Long getExpire() { return expire; } public void setExpire(Long expire) { this.expire = expire; } public String getBase64Img() { return base64Img; } public void setBase64Img(String base64Img) { this.base64Img = base64Img; }}

Redis封装类RedisUtils

网上随意找的,类里面注明来源,将就用,代码较多就不贴了,文末有代码获取

验证码方法层CaptchaService

package com.lzp.kaptcha.service;import com.lzp.kaptcha.utils.RedisUtils;import com.lzp.kaptcha.vo.CaptchaVO;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import java.util.UUID;@Servicepublicclass CaptchaService { @Value("${server.session.timeout:300}") private Long timeout; @Autowired private RedisUtils redisUtils; privatefinal String CAPTCHA_KEY = "captcha:verification:"; public CaptchaVO cacheCaptcha(String captcha){ //生成一个随机标识符 String captchaKey = UUID.randomUUID().toString(); //缓存验证码并设置过期时间 redisUtils.set(CAPTCHA_KEY.concat(captchaKey),captcha,timeout); CaptchaVO captchaVO = new CaptchaVO(); captchaVO.setCaptchaKey(captchaKey); captchaVO.setExpire(timeout); return captchaVO; }}

用户登录对象封装LoginDTO

package com.lzp.kaptcha.dto;publicclass LoginDTO { private String userName; private String pwd; private String captchaKey; private String captcha; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public String getCaptchaKey() { return captchaKey; } public void setCaptchaKey(String captchaKey) { this.captchaKey = captchaKey; } public String getCaptcha() { return captcha; } public void setCaptcha(String captcha) { this.captcha = captcha; }}

登录控制层UserController

这块我写逻辑代码了,相信大家都看的懂

package com.lzp.kaptcha.controller;import com.lzp.kaptcha.dto.LoginDTO;import com.lzp.kaptcha.utils.RedisUtils;import com.lzp.kaptcha.vo.UserVO;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/user")publicclass UserController { @Autowired private RedisUtils redisUtils; @PostMapping("/login") public UserVO login(@RequestBody LoginDTO loginDTO) { Object captch = redisUtils.get(loginDTO.getCaptchaKey()); if(captch == null){ // throw 验证码已过期 } if(!loginDTO.getCaptcha().equals(captch)){ // throw 验证码错误 } // 查询用户信息 //判断用户是否存在 不存在抛出用户名密码错误 //判断密码是否正确,不正确抛出用户名密码错误 //构造返回到前端的用户对象并封装信息和生成token returnnew UserVO(); }}

验证码获取和查看

图片

图片图片

来源:https://www.51cto.com/article/822372.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
2026上海科技节盛大开幕:科技嘉年华等你来体验

2026上海科技节盛大开幕:科技嘉年华等你来体验

2026年上海科技节于5月23日开幕,为期一周,覆盖全市16个区,计划举办近2000场活动。活动设置七大板块,涵盖专题会议、科普开放日、赛事及文旅体验等,旨在打造全民共享的科技嘉年华,让前沿科技与城市生活深度对话。通过多层次、可参与的场景设计,让市民直观感受科技如何塑造未来,推动科普从单向传。

时间:2026-05-23 14:40
Moka发布三款AI人力资源工具助力企业管理智能化

Moka发布三款AI人力资源工具助力企业管理智能化

随着人才供需变化与AI岗位激增,HR面临更复杂的人才匹配挑战。Moka近期推出三款AI工具:招聘Eva优化全流程筛选与面试,人事Eva处理高频事务,BPEva提供组织洞察。这些工具旨在将HR从繁琐工作中解放,聚焦战略与人才管理。AI的应用有望推动评价体系更客观,并重塑组织协作方式,但转型需克服固有工作惯性。

时间:2026-05-23 14:40
2026年618惠普星Book Pro轻薄本选购指南与推荐

2026年618惠普星Book Pro轻薄本选购指南与推荐

对于在校大学生而言,选择一台称心如意的笔记本电脑,需要综合考虑预算、性能、便携性与续航等多重因素。进入2026年,兼具高性价比、轻薄机身、长时续航与丰富接口的轻薄本,已成为校园学习与生活的主流装备。它不仅能流畅完成论文撰写、PPT制作、在线课程等日常学业任务,也能胜任轻度的平面设计、视频剪辑或编程开

时间:2026-05-23 14:39
尼康Z 70-200mm f/2.8镜头评测与选购指南

尼康Z 70-200mm f/2.8镜头评测与选购指南

尼康推出尼克尔Z70-200mmf 2 8VRSII镜头,作为第二代“大三元”成员,在光学、操控和轻量化方面显著升级。它采用全新镜片组合与涂层技术,有效抑制眩光,保证画质。镜头重量减轻约26%,长度缩短,采用内变焦设计,提升了便携性。实拍显示,其全开光圈下中心与边缘锐度出色,满足专业需求。

时间:2026-05-23 14:39
尼康Z 70-200mm f2.8 S镜头评测与选购指南

尼康Z 70-200mm f2.8 S镜头评测与选购指南

今年CP+展会上,尼康正式发布了备受期待的尼克尔 Z 70-200mm f 2 8 VR S II镜头。作为“大三元”长焦端的第二代产品,它不仅延续了专业血统,更在重量、画质和对焦性能上实现了显著跃升。对于专注于人像、远景等题材的摄影师而言,这支镜头是否带来了新的选择?我们深入体验了一番。 光学结构

时间:2026-05-23 14:39
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜
热门教程
更多
  • 游戏攻略
  • 安卓教程
  • 苹果教程
  • 电脑教程