SpringBoot结合SpringSecurity实现图形验证码功能
本文介绍了SpringBoot结合SpringSecurity实现图形验证码功能,分享给大家,具体如下:
生成图形验证码
- 根据随机数生成图片
- 将随机数存到Session中
- 将生成的图片写到接口的响应中
生成图形验证码的过程比较简单,和SpringSecurity也没有什么关系。所以就直接贴出代码了
根据随机数生成图片
/** *生成图形验证码 *@paramrequest *@return */ privateImageCodegenerate(ServletWebRequestrequest){ intwidth=64; intheight=32; BufferedImageimage=newBufferedImage(width,height,BufferedImage.TYPE_INT_RGB); Graphicsg=image.getGraphics(); Randomrandom=newRandom(); g.setColor(getRandColor(200,250)); g.fillRect(0,0,width,height); g.setFont(newFont("TimesNewRoman",Font.ITALIC,20)); g.setColor(getRandColor(160,200)); for(inti=0;i<155;i++){ intx=random.nextInt(width); inty=random.nextInt(height); intxl=random.nextInt(12); intyl=random.nextInt(12); g.drawLine(x,y,x+xl,y+yl); } StringsRand=""; for(inti=0;i<4;i++){ Stringrand=String.valueOf(random.nextInt(10)); sRand+=rand; g.setColor(newColor(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110))); g.drawString(rand,13*i+6,16); } g.dispose(); returnnewImageCode(image,sRand,60); } /** *生成随机背景条纹 * *@paramfc *@parambc *@return */ privateColorgetRandColor(intfc,intbc){ Randomrandom=newRandom(); if(fc>255){ fc=255; } if(bc>255){ bc=255; } intr=fc+random.nextInt(bc-fc); intg=fc+random.nextInt(bc-fc); intb=fc+random.nextInt(bc-fc); returnnewColor(r,g,b); }
将随机数存到Session中&&将生成的图片写到接口的响应中
@RestController publicclassValidateCodeController{ publicstaticfinalStringSESSION_KEY="SESSION_KEY_IMAGE_CODE"; privateSessionStrategysessionStrategy=newHttpSessionSessionStrategy(); @GetMapping("/code/image") publicvoidcreateCode(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{ ImageCodeimageCode=generate(newServletWebRequest(request)); sessionStrategy.setAttribute(newServletWebRequest(request),SESSION_KEY,imageCode); ImageIO.write(imageCode.getImage(),"JPEG",response.getOutputStream()); } }
在认证流程中加入图形验证码
在SpringSecurity认证流程详解中,我们有讲到,SpringSecurity是通过过滤器链来进行校验的,我们想要验证图形验证码,所以可以在认证流程之前,也就是UsernamePasswordAuthenticationFilter之前进行校验。
自定义图形验证码的过滤器
@Component publicclassValidateCodeFilterextendsOncePerRequestFilter{ privateSessionStrategysessionStrategy=newHttpSessionSessionStrategy(); privateAuthenticationFailureHandlerauthenticationFailureHandler; @Override protectedvoiddoFilterInternal(HttpServletRequesthttpServletRequest,HttpServletResponsehttpServletResponse,FilterChainfilterChain)throwsServletException,IOException{ if(StringUtils.equals("/user/login",httpServletRequest.getRequestURI()) &&StringUtils.equalsIgnoreCase(httpServletRequest.getMethod(),"post")){ try{ //1.进行验证码的校验 validate(newServletWebRequest(httpServletRequest)); }catch(ValidateCodeExceptione){ //2.如果校验不通过,调用SpringSecurity的校验失败处理器 authenticationFailureHandler.onAuthenticationFailure(httpServletRequest,httpServletResponse,e); return; } } //3.校验通过,就放行 filterChain.doFilter(httpServletRequest,httpServletResponse); } }
这里验证码校验的过程比较简单,主要就是判断传过来的参数和Session中保存的是否一致,以及Session中的验证码是否过期了。
有了自己的验证码过滤器之后,我们还需要将它配置在UsernamePasswordAuthenticationFilter之前:
@Override protectedvoidconfigure(HttpSecurityhttp)throwsException{ ValidateCodeFiltervalidateCodeFilter=newValidateCodeFilter(); validateCodeFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler); //将我们自定义的过滤器,配置到UsernamePasswordAuthenticationFilter之前 http.addFilterBefore(validateCodeFilter,UsernamePasswordAuthenticationFilter.class) .formLogin()//定义当需要用户登录时候,转到的登录页面。 //后面的配置省略 }
代码下载
Spring-Security
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。