kaptcha 验证码技术的应用

一.背景

图形验证码的生成与使用(防止机器恶意攻击)

二.代码(使用)

1.添加Maven依赖

<!--验证码 -->
<dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version><exclusions><exclusion><artifactId>javax.servlet-api</artifactId><groupId>javax.servlet</groupId></exclusion></exclusions>
</dependency>

2. 验证码配置类

package com.provider.auth.config;import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.code.kaptcha.util.Config;import java.util.Properties;/*** 验证码配置**/
@Configuration
public class CaptchaConfig {@Bean(name = "captchaProducer")public DefaultKaptcha getKaptchaBean() {DefaultKaptcha defaultKaptcha = new DefaultKaptcha();Properties properties = new Properties();// 是否有边框 默认为true 我们可以自己设置yes,noproperties.setProperty("kaptcha.border", "yes");// 边框颜色 默认为Color.BLACKproperties.setProperty("kaptcha.border.color", "105,179,90");// 验证码文本字符颜色 默认为Color.BLACKproperties.setProperty("kaptcha.textproducer.font.color", "blue");// 验证码图片宽度 默认为200properties.setProperty("kaptcha.image.width", "160");// 验证码图片高度 默认为50properties.setProperty("kaptcha.image.height", "60");// 验证码文本字符大小 默认为40properties.setProperty("kaptcha.textproducer.font.size", "30");// KAPTCHA_SESSION_KEYproperties.setProperty("kaptcha.session.key", "kaptchaCode");// 验证码文本字符间距 默认为2properties.setProperty("kaptcha.textproducer.char.space", "3");// 验证码文本字符长度 默认为5properties.setProperty("kaptcha.textproducer.char.length", "5");// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");// 验证码噪点颜色 默认为Color.BLACKproperties.setProperty("kaptcha.noise.color", "white");Config config = new Config(properties);defaultKaptcha.setConfig(config);return defaultKaptcha;}@Bean(name = "captchaProducerMath")public DefaultKaptcha getKaptchaBeanMath() {DefaultKaptcha defaultKaptcha = new DefaultKaptcha();Properties properties = new Properties();// 是否有边框 默认为true 我们可以自己设置yes,noproperties.setProperty("kaptcha.border", "yes");// 边框颜色 默认为Color.BLACKproperties.setProperty("kaptcha.border.color", "105,179,90");// 验证码文本字符颜色 默认为Color.BLACKproperties.setProperty("kaptcha.textproducer.font.color", "blue");// 验证码图片宽度 默认为200properties.setProperty("kaptcha.image.width", "160");// 验证码图片高度 默认为50properties.setProperty("kaptcha.image.height", "60");// 验证码文本字符大小 默认为40properties.setProperty("kaptcha.textproducer.font.size", "35");// KAPTCHA_SESSION_KEYproperties.setProperty("kaptcha.session.key", "kaptchaCodeMath");// 验证码文本生成器 【com.provider.auth.config.KaptchaTextCreator 自定义的验证码创建类 后面有附上】properties.setProperty("kaptcha.textproducer.impl", "com.provider.auth.config.KaptchaTextCreator");// 验证码文本字符间距 默认为2properties.setProperty("kaptcha.textproducer.char.space", "3");// 验证码文本字符长度 默认为5properties.setProperty("kaptcha.textproducer.char.length", "6");// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");// 验证码噪点颜色 默认为Color.BLACKproperties.setProperty("kaptcha.noise.color", "white");// 干扰实现类properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpyproperties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");Config config = new Config(properties);defaultKaptcha.setConfig(config);return defaultKaptcha;}
}

 

3. 验证码文本生成器 KaptchaTextCreator

 

package com.provider.auth.config;import java.util.Random;import com.google.code.kaptcha.text.impl.DefaultTextCreator;/*** 验证码文本生成器**/
public class KaptchaTextCreator extends DefaultTextCreator {private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");@Overridepublic String getText() {Integer result = 0;Random random = new Random();int x = random.nextInt(10);int y = random.nextInt(10);StringBuilder suChinese = new StringBuilder();int randomoperands = (int) Math.round(Math.random() * 2);if (randomoperands == 0) {result = x * y;suChinese.append(CNUMBERS[x]);suChinese.append("*");suChinese.append(CNUMBERS[y]);} else if (randomoperands == 1) {if (!(x == 0) && y % x == 0) {result = y / x;suChinese.append(CNUMBERS[y]);suChinese.append("/");suChinese.append(CNUMBERS[x]);} else {result = x + y;suChinese.append(CNUMBERS[x]);suChinese.append("+");suChinese.append(CNUMBERS[y]);}} else if (randomoperands == 2) {if (x >= y) {result = x - y;suChinese.append(CNUMBERS[x]);suChinese.append("-");suChinese.append(CNUMBERS[y]);} else {result = y - x;suChinese.append(CNUMBERS[y]);suChinese.append("-");suChinese.append(CNUMBERS[x]);}} else {result = x + y;suChinese.append(CNUMBERS[x]);suChinese.append("+");suChinese.append(CNUMBERS[y]);}suChinese.append("=?@" + result);return suChinese.toString();}}

4.接口的使用Controller 本controller是把生成的code放到redis里面并设置过期时间,每次请求前端携带UUID作为键

来标识那个验证码,还有一种方式是直接用session来储存这里不做过多的演示

package com.provider.auth.web;import java.awt.image.BufferedImage;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.config.redis.RedisHelper;
import com.core.base.web.AjaxResult;
import com.core.base.web.BaseController;
import com.core.constant.GlobalConstant;
import com.provider.auth.config.TokenDefaultTimeConfig;
import com.utils.common.ResponseUtils;
import com.utils.verify.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.google.code.kaptcha.Producer;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** 图片验证码(支持算术形式)**/
@RestController
@RequestMapping("/captcha")
@Api(tags = "图片验证码接口", description = "图片验证码接口")
public class CaptchaController extends BaseController {@Resource(name = "captchaProducer")private Producer captchaProducer;@Resource(name = "captchaProducerMath")private Producer captchaProducerMath;@Autowiredprivate RedisHelper redisHelper;@Autowiredprivate TokenDefaultTimeConfig tokenDefaultTimeConfig;/*** 验证码生成** @param request    HttpServletRequest* @param response   HttpServletResponse* @param type       captcha type* @param identifier identifier* @return AjaxResult* @author fangyi* @date 2019/5/17*/@ApiOperation(value = "验证码生成")@GetMapping(value = "/captchaImage")public AjaxResult getKaptchaImage(HttpServletRequest request,HttpServletResponse response,@RequestParam(value = "type") String type,@RequestParam("identifier") String identifier) {try {String capStr;String code = null;BufferedImage bufferedImage = null;// GlobalConstant.CAPTCHA_MATH 类型文尾有附if (GlobalConstant.CAPTCHA_MATH.equals(type)) {String capText = captchaProducerMath.createText();capStr = capText.substring(0, capText.lastIndexOf("@"));code = capText.substring(capText.lastIndexOf("@") + 1);bufferedImage = captchaProducerMath.createImage(capStr);} else if (GlobalConstant.CAPTCHA_CHAR.equals(type)) {capStr = code = captchaProducer.createText();bufferedImage = captchaProducer.createImage(capStr);}if (bufferedImage == null) {return AjaxResult.error("0401011");}// 放入redis中,并设置失效时间(默认10分钟)// 这里也可采用放入session中的方案redisHelper.set(identifier, code, tokenDefaultTimeConfig.getCaptchaValidity());// ResponseUtils工具类文尾有附ResponseUtils.responseBufferedImage(request, response, bufferedImage);} catch (Exception e) {e.printStackTrace();return AjaxResult.error("500");}return null;}/*** 验证码验证** @param code       captcha code* @param identifier identifier* @return AjaxResult* @author fangyi* @date 2019/5/17*/@ApiOperation(value = "验证码验证")@GetMapping(value = "/checkCaptchaImage")public AjaxResult checkCaptchaImage(@RequestParam(value = "code") String code,@RequestParam("identifier") String identifier) {String redisCode = (String) redisHelper.get(identifier);if (StringUtils.isBlank(redisCode)) {return AjaxResult.error("0401012");}if (!redisCode.equals(code)) {return AjaxResult.error("0401012");}return AjaxResult.success();}
}

5.结果展示

type 有以下两种方式(上面代码的常量如下)

/*** 验证码生成数学算术类型*/ String CAPTCHA_MATH = "math";

/*** 验证码生成字符串类型*/ String CAPTCHA_CHAR = "char";

type=math如图

http://localhost:8096/captcha/captchaImage?identifier=your UUID &type=math

type=char如图:

http://localhost:8096/captcha/captchaImage?identifier=your UUID &type=char

附:ResponseUtils 响应工具类

package com.utils.common;import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;import static java.lang.System.out;/*** 响应工具类**/
public class ResponseUtils {public ResponseUtils() {}public static void setResponseFileHeader(HttpServletRequest request, HttpServletResponse response, String filename, String type, Long size) throws UnsupportedEncodingException {String userAgent = request.getHeader("User-Agent");if (!userAgent.contains("MSIE") && !userAgent.contains("Trident")) {filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");} else {filename = URLEncoder.encode(filename, "UTF-8");}response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes(), "UTF-8"));response.addHeader("Content-Length", "" + size);response.setContentType("application/octet-stream");}public static void responseBufferedImage(HttpServletRequest request, HttpServletResponse response, BufferedImage bufferedImage) throws IOException {if (bufferedImage != null) {// 将bufferedImage写入HttpServletResponse OutputStream中ServletOutputStream out = null;try {response.setDateHeader("Expires", 0);response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");response.addHeader("Cache-Control", "post-check=0, pre-check=0");response.setHeader("Pragma", "no-cache");response.setContentType("image/jpeg");out = response.getOutputStream();ImageIO.write(bufferedImage, "jpg", out);out.flush();} finally {if (out != null) {out.close();}}}}}

AjaxResult为自定义返回结果类,可以自行自定义 如 code msg data 等

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

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

相关文章

王田苗对话四位AI领军人物:具身智能的机遇与挑战

一个新的机器人时代已经开启&#xff0c;几位顶级AI、机器人大佬&#xff0c;如何思考具身智能&#xff1f;大模型给机器人带来了怎样的变革意义&#xff1f;人形机器人多久能进入家庭&#xff1f; 从早稻田大学1972年研发的WABOT&#xff0c;到特斯拉2022年首秀的Optimus&…

玖章算术CEO叶正盛在数据技术嘉年华分享NineData AIGC的应用实践

4月8日下午&#xff0c;为期两天的第十二届数据技术嘉年华&#xff08;DTC 2023&#xff09;在北京新云南皇冠假日酒店圆满落下帷幕。大会得到了工业和信息化部电子五所的支持和指导&#xff0c;围绕“开源融合数字化——引领数据技术发展&#xff0c;释放数据要素价值”这一主…

软件技术基础知识忏悔录C#.NET篇(一)

为何开始 人已是大三之年&#xff0c;虽是身在985&#xff0c;心里却没有半分985的底气&#xff0c;自从大二分流以来&#xff0c;自己几乎是没再系统的学过什么&#xff0c;除了几位知识还算渊博的老师教了较为详细的数据库、数据结构的知识之外&#xff0c;其他老师大抵都是迷…

聊聊简历怎么写

大家好&#xff0c;我是柠檬哥。 年初看机会、准备换工作的同学比较多&#xff0c;后台也有很多同学请教如何准备面试&#xff0c;精力有限&#xff0c;一个个回复肯定是回不过来。 关于求职面试这块的的话题有点大&#xff0c;大部分人内心OS估计是&#xff1a; 忍了一年的SX领…

程序员该如何去写自己的简历-代码而成的简历

首先&#xff0c;声明这是写给程序员看的&#xff0c;而不是码农。其次&#xff0c;如果你不幸是码农那么请成为程序员。最后&#xff0c;码农和程序员是有区别的&#xff0c;程序员应该是有思想的手工艺人&#xff0c;在这个机械高度生产化的世界里&#xff0c;人口众多的手工…

【总结】1637- 如何利用 ChatGPT 提升 JavaScript 编程能力?

最新文章&#xff1a; 【工具】1636- 高效办公&#xff01;5款腾讯免费AI工具 【工具】1634- 提高工作效率&#xff0c;这 10 款 AI 工具不能错过&#xff01; 【分享】1632- 推荐 20 款顶级 AI 聊天机器人&#xff0c;轻松畅聊未来 最近几天&#xff0c;GPT-4、ChatGPT Plugin…

可以用什么软件画流程图?看看这几款画流程图软件

我们在日常的学习和工作中&#xff0c;经常会需要制作一些流程图来帮助我们梳理工作的流程或知识点&#xff0c;帮助我们能够更好地理清思路&#xff0c;让我们可以更加顺利地完成学习和工作任务。那大家知道在线画流程图工具有哪些吗&#xff1f;还不知道的小伙伴&#xff0c;…

绘制交互流程图的方法

转载自&#xff1a;http://blog.sina.com.cn/s/blog_6b6abdc10100wpny.html 下面介绍一个设计方法&#xff0c;这是一个用于兼顾“为流程”与“为结构”的信息架构&#xff08;IA&#xff09;的设计方法。是2010年底&#xff0c;我和seven共同分析总结出来的。在广州的“2010年…

分别画出程序的软件流程图、NS图、PAD图; 程序

1、分别画出程序的软件流程图、NS图、PAD图&#xff1b; 程序 #include<stdio.h> #include<stdlib.h> int main(int argc, char *argv[]) {int Edge_a,Edge_b,Edge_c;printf("Input three int type data between space:\n");scanf("%d %d %d"…

分享一个开源的流程图绘制软件--Diagram Designer

最近在写专利文件&#xff0c;在制作说明书附图时想到自己还只会用wps进行简单的绘制&#xff0c;于是想学习下&#xff0c;填补下这方面的短板。这两天查到了DiagramDesigner这个小工具&#xff0c;派上了大用场。用它写完了一个发明专利&#xff0c;还给zigbee产品设计了一个…

交互流程图用什么软件做?

产品经理在进行产品设计等工作时&#xff0c;会使用交互流程图来提高团队效率。这种流程图适用于传达方案、评审目标等需要团队协作的场景&#xff0c;视觉设计师、产品开发等工作团队只需看图便能迅速理解图示要义&#xff0c;极大地节省了理解时间&#xff0c;有效提高沟通效…

给菜鸟看的Android应用开发全流程

给菜鸟看的Android应用开发全流程——好多Android开发中&#xff0c;没人告诉过你的事 很多菜鸟开始学习Android开发&#xff0c;去网上搜集过很多“Android开发教程”&#xff0c;但是搜索出来的东西&#xff0c;如果不是特别针对性的关键词&#xff0c;基本上内容都是&#x…

对话钉钉音视频专家冯津伟:大模型不是万能的

策划&#xff1a;LiveVideoStack 在音视频技术领域&#xff0c;ICASSP 大会是行业的风向标会议&#xff0c;也是语音学界从业者研究下一代技术发展的盛宴。近期&#xff0c;国内外各大企业陆陆续续放出论文入顶会的消息&#xff0c;钉钉蜂鸣鸟音频实验室 2 篇论文也登上了 ICAS…

ChatGPT颠覆者来了!Auto-GPT强在哪?

ChatGPT自诞生以来&#xff0c;一直备受关注&#xff0c;人们感受到了人工智能的强大。 现在&#xff0c;一个更加强大的人工智能应用已经登场——Auto-GPT。 Auto-GPT的一大突破是&#xff0c;可以让AI自我提示&#xff0c;就是说&#xff0c;这个AI完全不需要咱们人类了。 什…

每日一皮:每天到公司 VS 工作一小时后

往期推荐 每日一皮&#xff1a;都 0202 年了&#xff0c;我怎么可能被骗呢&#xff1f; 每日一皮&#xff1a;用户“这个项目很容易嘛”&#xff5e; 每日一皮&#xff1a;客户期望 vs 最终产品 每日一皮&#xff1a;入职新公司第一周的感受... 每日一皮&#xff1a;小公司搞中…

XXXX直聘聊天机器人

XXXX直聘聊天机器人 想转岗到爬虫工程师&#xff0c;由于面试机会太少&#xff0c;而boss直聘又无法海投&#xff0c;决定做一个boss直聘机器人来帮我找工作。 一、基本需求 一个爬虫程序爬取需要的工作信息&#xff0c;存入数据库。 聊天机器人每天上午10点向未聊天的boss打…

每天加班的HR,时间都浪费在了这些琐事上?

编者按&#xff1a;随着无纸化办公的引入&#xff0c;为企业办公免去了非常多的成本浪费&#xff0c;那么OA系统是如何为无纸化办公助力的呢&#xff1f;让我们一起往下看。 HR每天的工作离不开招聘、员工入转调离信息、出勤排班、薪酬和工资单、绩效福利、培训、休假管理等等。…

一位程序员的一天工作清单:5:30下班,5:30起床

分享职场程序员生活、职场攻略、领导同事相处技巧和创业资源 文|洪生鹏 曾发布了一篇《一位程序员的一天清单》文章&#xff0c;简单描述了一位程序员了的一天日程安排。 文章发布后&#xff0c;得到了广大读者的欢迎&#xff0c;其中读者们的留言最为精彩了&#xff0c;比文章…

工作日志day01

1.No matching distribution found for virtualenv 查询了好多资料&#xff0c;最终找到问题所在&#xff1a; 2.根据上述果然报错ping: www.baidu.com: Temporary failure in name resolution 解决&#xff1a; 最终成功下载虚拟环境 3.cuda编程问题&#xff1a;根据代码运行环…

【第188期】游戏文案策划:薪水低、压力大,升职无望,怎么办?

我是酱油&#xff0c;这是第188期文章 收到一位想匿名的同学留言&#xff1a; 酱油哥&#xff0c;我已经入行两年&#xff0c;在一个平平无奇的小游戏公司打转。因为职场的高度&#xff0c;也完全限制了我的职场眼界&#xff0c;所以想向你请教一下&#xff0c;游戏文案的职场…