springboot图片验证码功能模块怎么实现-mile米乐体育

springboot图片验证码功能模块怎么实现

本篇内容主要讲解“springboot图片验证码功能模块怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springboot图片验证码功能模块怎么实现”吧!

具体效果如下:

第一步:工具类

该工具类为生成验证码图片的核心,直接拷贝到项目即可,无需做修改;可个性化的参数全部对外提供的api,比如 字体大小背景颜色,干扰线数量高宽等都可以根据自己的需求设置对应参数;

代码几乎每一行都加了详细的注释;如果遇上特殊的个性化需求,调整一下这个工具类即可实现。

packagecom.feng.util;/***@returnnull*@authorladidol*@description*@date2022/4/1122:15*/importjava.awt.*;importjava.awt.geom.affinetransform;importjava.awt.image.bufferedimage;importjava.util.random;/***图形验证码生成*/publicclassverifyutil{//默认验证码字符集privatestaticfinalchar[]chars={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};//默认字符数量privatefinalintegersize;//默认干扰线数量privatefinalintlines;//默认宽度privatefinalintwidth;//默认高度privatefinalintheight;//默认字体大小privatefinalintfont_size;//默认字体倾斜privatefinalbooleantilt;privatefinalcolorbackground_color;/***初始化基础参数**@parambuilder*/privateverifyutil(builderbuilder){size=builder.size;lines=builder.lines;width=builder.width;height=builder.height;font_size=builder.fontsize;tilt=builder.tilt;background_color=builder.backgroundcolor;}/***实例化构造器对象**@return*/publicstaticbuildernewbuilder(){returnnewbuilder();}/***@return生成随机验证码及图片*object[0]:验证码字符串;*object[1]:验证码图片。*/publicobject[]createimage(){stringbuffersb=newstringbuffer();//创建空白图片bufferedimageimage=newbufferedimage(width,height,bufferedimage.type_int_rgb);//获取图片画笔graphics2dgraphic=image.creategraphics();//设置抗锯齿graphic.setrenderinghint(renderinghints.key_antialiasing,renderinghints.value_antialias_on);//设置画笔颜色graphic.setcolor(background_color);//绘制矩形背景graphic.fillrect(0,0,width,height);//画随机字符randomran=newrandom();//graphic.setbackground(color.white);//计算每个字符占的宽度,这里预留一个字符的位置用于左右边距intcodewidth=width/(size 1);//字符所处的y轴的坐标inty=height*3/4;for(inti=0;i

第二步:图片生成:

使用默认参数:

//生成图片验证码object[]verify=verifyutil.newbuilder().build().createimage();

自定义参数生成:

//这个根据自己的需要设置对应的参数来实现个性化//返回的数组第一个参数是生成的验证码,第二个参数是生成的图片object[]objs=verifyutil.newbuilder().setwidth(120)//设置图片的宽度.setheight(35)//设置图片的高度.setsize(6)//设置字符的个数.setlines(10)//设置干扰线的条数.setfontsize(25)//设置字体的大小.settilt(true)//设置是否需要倾斜.setbackgroundcolor(color.white)//设置验证码的背景颜色.build()//构建verifyutil项目.createimage();//生成图片

整合到springboot项目中:

需要引入的maven依赖:

org.springframework.bootspring-boot-starter-data-redisorg.apache.commonscommons-pool2net.jodahexpiringmap0.5.10

获取相关的验证码:

service层:

packagecom.feng.service;importorg.cuit.epoch.result.result;importjavax.servlet.http.httpservletrequest;importjavax.servlet.http.httpservletresponse;importjava.io.ioexception;/***@returnnull*@authorladidol*@description*@date2022/4/1122:15*/publicinterfaceverifyservice{/***创建图片验证码*@paramresponse*@paramrequest*@throwsioexception*/voidcreatecode(httpservletresponseresponse,httpservletrequestrequest)throwsioexception;/***检查图片验证码*@param*@param*@throwsioexception*/resultcheckcode(stringverificationcode);}

serviceimpl层:

packagecom.feng.service.impl;importcom.feng.service.verifyservice;importcom.feng.util.redisserviceimpl;importcom.google.common.net.httpheaders;importcom.feng.util.verifyutil;importorg.springframework.http.responsecookie;importorg.springframework.stereotype.service;importjavax.annotation.resource;importjavax.imageio.imageio;importjavax.servlet.http.httpservletrequest;importjavax.servlet.http.httpservletresponse;importjavax.servlet.http.httpsession;importjava.awt.image.bufferedimage;importjava.io.ioexception;importjava.io.outputstream;importjava.time.duration;/***@returnnull*@authorladidol*@description*@date2022/4/1122:15*/@servicepublicclassverifyserviceimplimplementsverifyservice{@resourceredisserviceimplredisutil;/***生成图片验证码*@paramresponse*@paramrequest*@throwsioexception*/@overridepublicvoidcreatecode(httpservletresponseresponse,httpservletrequestrequest)throwsioexception{//获取sessionhttpsessionsession=request.getsession();//获得sessionidstringid=session.getid();system.out.println();responsecookiecookie=responsecookie.from("jsessionid",id).secure(true).domain("").path("/").maxage(duration.ofhours(1)).samesite("none").build();//清除之前缓存的图片验证码if(!string.valueof(request.getsession().getattribute("session_verify_code_" id)).isempty()){stringgetverify=string.valueof(request.getsession().getattribute("session_verify_code_" id));redisutil.del(getverify);system.out.println("清除成功");}//生成图片验证码,用的默认参数object[]verify=verifyutil.newbuilder().build().createimage();//将验证码存入sessionsession.setattribute("session_verify_code_" id,verify[0]);//打印验证码system.out.println(verify[0]);//将验证码存入redisredisutil.set((string)verify[0],id,5*60);//将图片传给浏览器bufferedimageimage=(bufferedimage)verify[1];response.setcontenttype("image/png");response.setheader(httpheaders.set_cookie,cookie.tostring());outputstreamops=response.getoutputstream();imageio.write(image,"png",ops);}@overridepublicresultcheckcode(stringverificationcode){if(!redisutil.haskey(verificationcode)){returnnewresult<>(false,"验证码错误");}redisutil.del(verificationcode);returnr.success();}}

这里面还会用到redis相关的工具类,我就不列出来了,想要的话可以看我以前的博客工具类戳这里

controller层:
这里有用到@requiredargsconstructor, 就是简单的注入而已, 如果想要详细了解戳这里

packagecom.feng.controller;importlombok.requiredargsconstructor;importcom.feng.annotation.limitrequest;importcom.feng.service.verifyservice;importorg.springframework.web.bind.annotation.*;importjavax.servlet.http.httpservletrequest;importjavax.servlet.http.httpservletresponse;importjava.io.ioexception;/***@returnnull*@authorladidol*@description这里主要就是多种验证码和登录相关的东西*@date2022/4/1121:46*/@restcontroller@requestmapping("/verify")@requiredargsconstructor//这是在lombok工具给的注入方式,真帅publicclassverifycontroller{privatefinalverifyserviceverifyservice;/***获取图片验证码*/@limitrequest(count=5)//这个注解就是表示,你在限制时间里(我们这里默认是六秒钟),只能请求五次@getmapping("/getcode")publicvoidgetcode(httpservletresponseresponse,httpservletrequestrequest)throwsioexception{verifyservice.createcode(response,request);}@limitrequest(count=5)//这个注解就是表示,你在限制时间里(我们这里默认是六秒钟),只能请求五次@getmapping("/checkcode")publicresultcheckcode(stringcode){returnverifyservice.checkcode(code);}}

这里为了不被一直无限制的访问该服务, 我们用了一个限制ip访问次数的注解@limitrequest

annotion包下的注解类:

packagecom.feng.annotation;importjava.lang.annotation.*;/***@returnnull*@authorladidol*@description限制ip访问次数注解*@date2022/4/1122:15*/@documented@target(elementtype.method)//说明该注解只能放在方法上面@retention(retentionpolicy.runtime)public@interfacelimitrequest{longtime()default6000;//限制时间单位:毫秒intcount()default3;//允许请求的次数}

aspect包下的切面类:

packagecom.feng.aspect;importnet.jodah.expiringmap.expirationpolicy;importnet.jodah.expiringmap.expiringmap;importorg.aspectj.lang.proceedingjoinpoint;importorg.aspectj.lang.annotation.around;importorg.aspectj.lang.annotation.aspect;importorg.aspectj.lang.annotation.pointcut;importcom.feng.annotation.limitrequest;importorg.cuit.epoch.exception.appexception;importorg.springframework.stereotype.component;importorg.springframework.web.context.request.requestattributes;importorg.springframework.web.context.request.requestcontextholder;importorg.springframework.web.context.request.servletrequestattributes;importjavax.servlet.http.httpservletrequest;importjava.util.concurrent.concurrenthashmap;importjava.util.concurrent.timeunit;/***@returnnull*@authorladidol*@description*@date2022/4/1122:15*/@aspect@componentpublicclasslimitrequestaspect{privatestaticconcurrenthashmap>book=newconcurrenthashmap<>();//定义切点//让所有有@limitrequest注解的方法都执行切面方法@pointcut("@annotation(limitrequest)")publicvoidexcudeservice(limitrequestlimitrequest){}@around("excudeservice(limitrequest)")publicobjectdoaround(proceedingjoinpointpjp,limitrequestlimitrequest)throwsthrowable{//获得request对象requestattributesra=requestcontextholder.getrequestattributes();servletrequestattributessra=(servletrequestattributes)ra;httpservletrequestrequest=sra.getrequest();//获取map对象,如果没有则返回默认值//第一个参数是key,第二个参数是默认值expiringmapuc=book.getordefault(request.getrequesturi(),expiringmap.builder().variableexpiration().build());integerucount=uc.getordefault(request.getremoteaddr(),0);if(ucount>=limitrequest.count()){//超过次数,不执行目标方法system.out.println("接口请求超过次数!");thrownewappexception("接口请求超过次数!");}elseif(ucount==0){//第一次请求时,设置有效时间//uc.put(request.getremoteaddr(),ucount 1,expirationpolicy.created,limitrequest.time(),timeunit.milliseconds);}else{//未超过次数,记录加一uc.put(request.getremoteaddr(),ucount 1);}book.put(request.getrequesturi(),uc);//result的值就是被拦截方法的返回值objectresult=pjp.proceed();returnresult;}}

为了捕获全局的异常抛出, 且符合restful规范我们加一个这个处理类:

handle包下面的全局异常类:

packageorg.cuit.epoch.handler;importlombok.extern.log4j.log4j2;importorg.cuit.epoch.exception.appexception;importorg.cuit.epoch.result.r;importorg.cuit.epoch.result.result;importorg.springframework.web.bind.annotation.controlleradvice;importorg.springframework.web.bind.annotation.exceptionhandler;importorg.springframework.web.bind.annotation.responsebody;@controlleradvice@log4j2publicclassglobalexceptionhandler{@exceptionhandler(exception.class)@responsebodypublicresulterror(exceptione){log.error(e.getmessage());e.printstacktrace();returnr.fail(e.getmessage());}@exceptionhandler(appexception.class)@responsebodypublicresulterror(appexceptione){log.error(e.getmessage());e.printstacktrace();returnr.fail(e.getmessage());}}

application.yaml文件:

spring:cache:type:redisredis:#redis连接配置host:自己redis的ip地址port:redis端口password:密码jedis:pool:max-active:8max-wait:-1msmax-idle:500min-idle:0lettuce:shutdown-timeout:0ms

最终项目结构如下:

先得到一个验证码:

验证一下是否成功:

成功结果:

验证失败结果:

当请求在规定时间内的请求数超过规定的数量时或有报错:

到此,相信大家对“springboot图片验证码功能模块怎么实现”有了更深的了解,不妨来实际操作一番吧!这里是恰卡编程网网站,更多相关内容可以进入相关频道进行查询,关注mile米乐体育,继续学习!

展开全文
内容来源于互联网和用户投稿,文章中一旦含有米乐app官网登录的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系米乐app官网登录删除

最新文章

网站地图