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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。