vue+springboot实现图形验证码Kaptcha

1、前端

form使用了element-ui的组件,主要还是看img标签,src绑定了form.imgCodeUrl数据,点击图片时触发refreshCode更新图片验证码。

	  <el-form-item prop="verificationCode" label="验证码" style="text-align: left;">
		  <el-input v-model="form.verificationCode" placeholder="请输入验证码" style="width: 120px;vertical-align: top;"></el-input>
		  <img id="img" alt="验证码" @click="refreshCode" :src="form.imgCodeUrl" style="padding-left: 12px;"/>
	  </el-form-item>
    data() {
      return {
        form: {
          username: '',
          password: '',
		  verificationCode:'',
		  imgCodeUrl:this.$verificationCodeUrl,
        },
    ...
	...
  refreshCode(){
	  this.form.imgCodeUrl=this.$verificationCodeUrl+"?d="+new Date().getTime();
  }	

上面refreshCode更新图片验证码的原理,其实就是在原网址后添加随机的参数来改变form.imgCodeUrl网址,实现img标签自动刷新请求。

  • this.$verificationCodeUrl是请求的网址,这里设置成全局常量写在了main.js中
//验证码地址
Vue.prototype.$verificationCodeUrl="http://127.0.0.1/api/createImageCode";

2、后端实现生成createImageCode验证码图片

使用kaptcha生成图片验证码,添加如下依赖

<dependency>
     <groupId>com.github.penggle</groupId>
     <artifactId>kaptcha</artifactId>
     <version>2.3.2</version>
</dependency>

配置kaptcha图片生成规则

...
import java.util.Properties;
 
@Configuration
public class KaptchaConfig {
    @Bean
    public DefaultKaptcha getDefaultKaptcha() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        // 图片宽
        properties.setProperty("kaptcha.image.width", "130");
        // 图片高
        properties.setProperty("kaptcha.image.height", "50");
        // 图片边框
        properties.setProperty("kaptcha.border", "yes");
        // 边框颜色
        properties.setProperty("kaptcha.border.color", "105,179,90");
        // 字体颜色
        properties.setProperty("kaptcha.textproducer.font.color", "blue");
        // 字体大小
        properties.setProperty("kaptcha.textproducer.font.size", "40");
        // session key
        properties.setProperty("kaptcha.session.key", "imageCode");
        // 验证码长度
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        // 字体
        properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}

生成验证码的图片通过response.getOutputStream流发送到前端,而验证码保存到session域中,等待用户登录表单提交时进行校验匹对

	...
	@Autowired
	private DefaultKaptcha defaultKaptcha;
	...
	//生成图片验证码
	@GetMapping("/createImageCode")
	public void createImageCode(HttpServletRequest request,HttpServletResponse response) {
		response.setHeader("Cache-Control", "no-store, no-cache");
		response.setContentType("image/jpeg");
		// 生成文字验证码
		String text = defaultKaptcha.createText();
		// 生成图片验证码
		BufferedImage image = defaultKaptcha.createImage(text);
		//保存到session域
		HttpSession session = request.getSession();
		session.setAttribute("imageCode",text);
		ServletOutputStream out = null;
		try {
			//响应输出图片流
			out = response.getOutputStream();
			ImageIO.write(image, "jpg", out);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				out.flush();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

3、前端提交表单

代码有点长,其实是嵌套了三层,第一层if (valid)判断表单校验(填入的数据是否符合规则),第二层this. h t t p . g e t ( " / v e r i f y I m a g e C o d e " 提交验证码判断验证码是否正确,第三层 t h i s . http.get("/verifyImageCode"提交验证码判断验证码是否正确,第三层this. http.get("/verifyImageCode"提交验证码判断验证码是否正确,第三层this.http.post("/user/login"最后判断用户名和密码是否正确,三层逻辑都通过才保存用户登录信息。

      submitForm() {
        this.$refs.form.validate(valid => {
		  //表单校验通过
          if (valid) {
			//先判断图形验证码
			this.$http.get("/verifyImageCode",{params:{verificationCode:this.form.verificationCode}})
			.then((response)=>{
				//图形验证码成功
				if(response.data.code === 0){
					//判断用户名和密码
					this.$http.post("/user/login",{
						username:this.form.username,
						password:this.form.password
					})
					.then((response)=>{
						if(response.data.code === 0){//登录成功
							this.$message({
							  message: '登录成功',
							  type: 'success',
							});
							localStorage.setItem("user",JSON.stringify(response.data.data));//保存用户信息
							this.$router.push("/");
						}
						else{
							this.$message.error("用户名或密码错误,请重试!!!");
						}
					})
					.catch((error)=>{
						//未接受到response的网络传输等错误
						console.log(error);
					});
				}else{//图形验证码错误
					this.$message.error(response.data.data.message);
					return;
				}
			})
			.catch((error)=>{
				//未接受到response的网络传输等错误
				console.log(error);
				return;
			});	
          } else {
            this.$message.error('表单填写错误,请检查');
            return false;
          }
        });
        //无论成功还是失败都刷新图形验证码
		this.refreshCode();
      },

4、后端/verifyImageCode验证码匹对

CommonResult是自定义的返回数据结果类,可以搜我以前文章。前端传来的验证码与session域中的匹对。

	//匹对图片验证码
	@GetMapping("/verifyImageCode")
	public CommonResult<Object> verifyImageCode(String verificationCode,HttpServletRequest request) {
		HttpSession session = request.getSession();
		if(session.getAttribute("imageCode").equals(verificationCode)) {
			return CommonResult.success();
		}else {
			return CommonResult.failed(ErrorCode.IMG_CODE_VERIFY_ERROR.getCode(), Message.createMessage(ErrorCode.IMG_CODE_VERIFY_ERROR.getMessage()));
		}
	}

5、bug

测试时,验证码图片能够生成显示,并能刷新。但提交表单时,对/verifyImageCode的请求返回错误码500。
首先打印发现session域的值为null。了解到原来session会话是有唯一的session id。打印session id,发现每次请求session id的不一样。session id其实是存在在cookie里的。
所以前端发送请求时要携带cookie证书,vue配置

//携带证书 session id
axios.defaults.withCredentials = true

后端的跨域配置也要允许证书通行

//配置跨域过滤器CorsFilter
@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        //允许证书
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        List<String> list = Arrays.asList("*");
        corsConfiguration.setAllowedHeaders(list);
        corsConfiguration.setAllowedMethods(list);
        corsConfiguration.setAllowedOriginPatterns(list);
        source.registerCorsConfiguration("/**", corsConfiguration);
        CorsFilter corsFilter = new CorsFilter(source);
        return corsFilter;
    }
}

还没完,请求还是返回500。浏览器调试器显示如下
在这里插入图片描述
请求头中已经带cookie,然而响应头又set-cookie了,也就是cookie里的session id又被重置,为什么这样子?可能是感叹号报错的原因:set-cookie默认属性是"SameSite=Lax,"。参考网上文章,我们修改后端配置application.properties:

#获取同一个session id的cookie设置
server.servlet.session.cookie.secure=true
server.servlet.session.cookie.same-site=none

再运行起来,set-cookie和感动号消失,调试通过。

参考文章:vue+springboot实现登录验证码

6、扩展

后来发现Hutool里也有图形验证码工具,链接。理解了上述基础,能更好该工具。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【informer】 时间序列的预测学习 2021 AAAI best paper

文章目录 前言1.引入2.数据集3. 训练4其它【待续】 前言 数据集 https://github.com/zhouhaoyi/ETDataset/blob/main/README_CN.md 代码&#xff1a;https://github.com/zhouhaoyi/Informer2020#reproducibility 21年的paper:https://arxiv.org/pdf/2012.07436.pdf 论文在代码…

1. redis入门到放弃

使用shutdown命令的时候&#xff0c;会在关机的同时生成一个RDB文件&#xff0c;使数据不丢失。redis虽然有16个库&#xff0c;但是基本上只会用0库&#xff0c;用其他的库没有意义。集群只能在0号库做mysql的读写&#xff0c;大约为写入600笔/s,读2000笔/s 一、Redis全局命令…

AI变现之数字人工具库账号引流

信息差无处不在&#xff0c;AI 发展到今天虽然工具和技术都日趋成熟&#xff0c;但是在国内普及率还不是很高&#xff0c;对于很多普通人估计也就听过 Chatgpt&#xff0c;MJ&#xff0c;SD 等 AI 工具的名词&#xff0c;但是没有真正的使用过&#xff0c;而使用 AI 数字人制作…

【Git学习一】初始化仓库git init的使用和提交git add与git commit的使用

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;Git等软件工具技术的使用 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要…

dvwa 文件上传漏洞通关攻略

dvwa 文件上传漏洞通关攻略 文章目录 dvwa 文件上传漏洞通关攻略low等级mediumhighimpossible 练习文件上传漏洞的攻击与防御 low等级 点击文件上传进行测试上传个一句话木马 <?php eval($_REQUEST[777]);?>上传成功 访问上传路径 进行蚁剑连接 代码审计 <?ph…

在市场发展中寻变革,马上消费金融树行业发展“风向标”

11月11日&#xff0c;2023金融街论坛年会第三届全球金融科技大会“金融科技创新与合规安全”平行论坛在北京召开。会上&#xff0c;马上消费金融副总经理孙磊就数据对金融的赋能作用、数据安全治理等方面展开了深度讨论。 公开信息显示&#xff0c;马上消费金融是一家经中国银保…

1. hadoop环境准备

环境准备 准备三台虚拟机&#xff0c;配置最好是 2C 4G 以上 本文准备三台机器的内网ip分别为 172.17.0.10 172.17.0.11 172.17.0.12本机配置/etc/hosts cat >> /etc/hosts<<EOF 172.17.0.10 hadoop01 172.17.0.11 hadoop02 172.17.0.12 hadoop03 EOF本机设置与…

ChatGPT简介及基本概念

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列点击跳转>ChatGPT和AIGC &#x1f449;关于作者 专…

如何利用自动发现将现网的进程纳入到监控系统中?

进程监控是一项关键任务&#xff0c;旨在监测系统中运行的进程的性能和状态。通过有效的进程监控&#xff0c;可以实时了解进程的运行情况&#xff0c;及时发现问题并采取措施&#xff0c;确保系统的稳定性和性能。 本期EasyOps产品使用最佳实践&#xff0c;我们将为您揭晓&am…

leetCode 21.合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#xff1a;[]…

soh估计:Data-driven prediction of battery cycle life before capacity degradation

文献思想 作者发现不同循环寿命的电池&#xff0c;第100次和第10次循环放电容量的差有不同&#xff0c;作者由这一现象&#xff0c;提取出了放电容量差的方差、平均值、最小值等特征&#xff0c;其中放电容量差的方差对数和循环寿命的对数的皮尔逊相关性高达-0.93&#xff0c;…

第四代管网水位监测仪:管网水位监测仪效果怎么样?

随着我国城市化进程的推进&#xff0c;随之而来的是城市规模不断扩大&#xff0c;各类排水管网设施需要检查的范围也日益扩大。尽管市政管理部门已安排人员定期巡查&#xff0c;但仍无法对井下水位进行24小时实时监控。如遇管网阻塞、窨井满溢等情况&#xff0c;若不及时处理将…

Jenkins-Windows节点-参数传入中文乱码的问题

方法一 设置环境变量 变量名&#xff1a;JAVA_TOOL_OPTIONS 变量值&#xff1a;-Dfile.encodingUTF8 还是有部分中文会乱码&#xff0c;进行区域设置

NewStarCTF2023 Reverse方向Week3 ez_chal WP

分析 题目&#xff1a;ez_chal 一个XTEA加密&#xff0c; V6是key&#xff0c;v5是输入&#xff0c;然后v7就是密文。 看了v6&#xff0c;要用动调。 ELF文件用ida的远程调试。 然后在kali上输入长度为32的flag 全部转换成dd 再提取密文。 EXP #include <stdio.h>…

使用阿里云Logstash,从自建es6.2.4迁移数据至云ES7.10测试

一、购买阿里云Logstash服务 4C16G 40G 高效云盘 二、配置管道 2.1 配置启动管道前置工作 logstash要通源端ES网络及http端口,且加白logstash要通目标端ES网络及http端口,且加白目标端ES加配置自动创建索引配置管道前先安装 logstash-output-file_extend插件目标云ES7.10要…

计算机组成原理——第一章

早期冯诺依曼机&#xff1a; 现代计算机&#xff1a; 五大部分&#xff1a; 1. 输入设备&#xff0c;是指将外部信息以计算机能读懂的方式输入进来&#xff0c;如键盘&#xff0c;鼠标等 2.输出设备&#xff0c;就是将计算机处理的信息以人所能接受的方式输出出来&#xff0c;比…

《C++避坑神器·二十二》VS能正常运行程序,但运行exe程序无响应解决办法

原因是某个文件只是放在了项目路径下&#xff0c;没有放在exe路径下&#xff0c;比如Json文件原来只放在了mlx项目下&#xff0c;导致VS可以运行&#xff0c;但运行exe无响应或报错如下&#xff1a; 两种方式修改&#xff1a; 1、把Json文件拷贝一份放到exe路径下 2、利用生成…

企业版远程软件推荐

在当今的数字时代&#xff0c;为您的企业配备远程访问功能至关重要。通过远程访问&#xff0c;您的团队可以在办公室外工作&#xff0c;并且无论身在何处都可以保持相同的生产力水平。在本文中&#xff0c;我们汇总了市场上的四大选择。 我们在远程访问解决方案中寻找什么 远…

为什么要用kubernetes?

第一章 kubernetes介绍 本章节主要介绍应用程序在服务器上部署方式演变以及kubernetes的概念、组件和工作原理。 应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个时代&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物…