vue+springboot实现图形验证码Kaptcha

news2024/10/7 8:28:22

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

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实现登录验证码

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

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

相关文章

SpringBoot和Spring源码下载

1.下载&#xff1a;在一个空的干净地创建一个文件夹叫springsourcecode&#xff0c;其实叫什么都行的。 git clone https://github.com/spring-projects/spring-framework.git 2.JDK要和gradle匹配 我们要21的&#xff0c;今天为止2023年11月13日&#xff0c;idea是2023.2。 …

软件测试/测试开发丨接口自动化测试学习笔记,加密与解密

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/28019 一、原理 在得到响应后对响应做解密处理&#xff1a; 如果知道使用的是哪个通用加密算法的话&#xff0c;可以自行解决。如果不了解对应的加密算法…

利用网络管理解决方案简化网络运维

当今的网络正朝着提高敏捷性和动态功能的方向发展&#xff0c;以支持高级网络要求和关键业务流程&#xff0c;这导致 IT 基础架构也跨越无线、虚拟和混合环境。但是&#xff0c;随着网络的快速发展&#xff0c;如果没有合适的解决方案&#xff0c;IT 管理员很难管理它们&#x…

为开发GPT-5,OpenAI向微软寻求新融资

11月14日&#xff0c;金融时报消息&#xff0c;OpenAI正在向微软寻求新一轮融资&#xff0c;用于开发超级智能向AGI&#xff08;通用人工智能&#xff09;迈进&#xff0c;包括最新模型GPT-5。 最近&#xff0c;OpenAI召开了首届开发者大会&#xff0c;推出了GPT-4 Turbo、自定…

完全未接触过软件测试的人,培训两个月就可上岗,这现实吗?

如果你想两个月能学完是可以的&#xff0c;但是只能做一些简单的功能测试&#xff0c;但也只限下面这四种情况 1.自身基础较好&#xff0c;自控力较强 比如一个计算机专业的学生要入行软件测试&#xff0c;可能就不需要进行入门培训了&#xff0c;自己找点视频看看就能很快上…

web 渗透 信息搜集

一 收集域名信息 1.whois查询 whois&#xff08;读作“Who is”&#xff0c;非缩写&#xff09;&#xff0c;标准的互联网协议&#xff0c…

光伏仪器-87110A/B太阳辐照度计

87110A/B 太阳辐照度计 光伏仪器 一款小巧、全数字化的太阳辐照度测试仪表&#xff0c;通过标准太阳电池测试太阳辐照度&#xff0c;并自带温度修正功能。太阳辐照度计集成了环境温度、电池板温度、倾斜角等测试功能&#xff0c;可以通过附带的蓝牙或串行接口连至电脑或智能…

运营商大数据是新时期贷款公司精准拓客的生命!!是企业的灵魂

贷款客户资源主要根据运营商大数据建模分析网站、app等&#xff0c;获取每天的网站实时访客&#xff0c;app活跃用户使用者数据的信息资源。 而贷款客户资源精准获客平台能帮您做的&#xff0c;就是根据用户实时动态轨迹与通信上网数据&#xff0c;锁定潜在意向客户&#xff0…

数据恢复入门分享-启动扇区

启动扇区位于存储区的前端&#xff0c;一般显示如下 如果扇区数据丢失或者错误 存储器也就不能识别和数据存储了 关注我们&#xff0c;不定期分享互联网数字化的干货 #数据恢复##储存卡##启动扇区#

【算法】最短路径——迪杰斯特拉 (Dijkstra) 算法

目录 1.概述2.代码实现2.1.节点类2.2.邻接矩阵存储图2.3.邻接表存储图2.4.测试 3.扩展3.1.只计算一对顶点之间的最短路径3.2.获取起点到其它节点具体经过的节点 4.应用 本文参考&#xff1a; LABULADONG 的算法网站 1.概述 &#xff08;1&#xff09;在图论中&#xff0c;最短…

小DEMO:在vue中自定义range组件

1、组件样式 2、使用 import cSlider from /components/c-slider/c-slider.vue<div class"range"><cSlider v-model"cScale" change"cScaleChange" :min"1" :max"10"/> </div> 3、组件代码 <templa…

VS2022配置wxWidgets 3.0.5

Downloads - wxWidgets下载Windows ZIP 解压进入E:\SoftWare\wxWidgets-3.0.5\build\msw&#xff0c;用VS2022打开wx_vc12.sln&#xff0c;选择生成——批生成&#xff0c;最终生成一些文件 打开VS2022&#xff0c;新建属性表&#xff0c;在属性表里设置&#xff1a; c——常规…

百度搜索智能化算力调控分配方法

作者 | 泰来 导读 随着近年深度学习技术的发展&#xff0c;搜索算法复杂度不断上升&#xff0c;算力供给需求出现了爆发式的增长。伴随着AI技术逐步走到深水区&#xff0c;算法红利在逐步消失&#xff0c;边际效应日益显著&#xff0c;算力效能的提升尤为重要&#xff0c;同时随…

海报设计必备!五个免费网站分享,让你的创意得以充分展现!

海报作为一种重要的宣传工具&#xff0c;在各种场合得到了广泛的应用。然而&#xff0c;对许多人来说&#xff0c;制作一张漂亮的海报并不容易。幸运的是&#xff0c;有许多免费的海报制作网站可以帮助人们轻松地制作出漂亮的海报。本文将分享五个优秀的免费海报制作网站。 1.…

天津专升本新版报名系统网上报名、填志愿、缴费、审核等操作步骤

天津高职升本网上报名、填报志愿新版专升本报名系统 ▏报名入口&#xff1a;www.zhaokao.net▏注意&#xff1a;一定要在截止时间内完成报名、填报志愿、缴费、审核、下载《报名信息表》等4步骤▏可报考院校及专业请参考招生院校发布的通知&#xff08;招生简章、报考须知&…

实时level2访问与策略研发

本周四下午4点&#xff0c;天软会聚焦“实时&level2访问与策略研发”开展我们的天软高频时序数仓会议&#xff0c;本次会议的报名客户&#xff0c;可以申请试用LEVEL-2数据测试账号哦~

jeesite 按部门过滤数据权限(保姆级图文教程)

文章目录 前言一、数据库表添加机构字段二、修改实体3.修改服务层总结前言 在项目开发过程中,数据需要按照部门、公司进行权限过滤,本篇文章记录下如何修改按部门进行权限过滤的详细图文教程。 一、数据库表添加机构字段 要进行权限过滤的表中添加机构字段 二、修改实体 添…

考研分享第3期 | 211本378分上岸大连理工电子信息经验贴

考研分享第3期 | 211本378分上岸大连理工电子信息经验贴 一、个人信息 姓名&#xff1a;Ming 本科院校&#xff1a;某211学校电子信息工程学院 电子科学与技术专业 上岸院校&#xff1a;大连理工大学 电子信息与电气工程学部 电子信息&#xff08;0854&#xff09; 择校意…

【案例】由coredump引起的思考:程序的加载流程

背景 小米项目的同事&#xff0c;最近遇到了一个crash问题&#xff0c;困扰较久&#xff0c;向我请求帮助。&#xff08;其实是客户指定要求我来分析这个问题&#xff0c;该项目之前是由我负责的&#xff0c;帮客户解决很多较多crash问题。估计是实力得到了客户认可吧&#xff…

数据中心:精密空调监控,这招太高效了!

在当今日益复杂的工业环境中&#xff0c;精密空调系统的监控和管理变得至关重要。随着科技的迅猛发展&#xff0c;各行各业对温度、湿度和空气质量等参数的高度控制需求不断增加。 精密空调监控系统通过实时数据采集、分析和反馈&#xff0c;为企业提供了可靠的手段来确保生产环…