来自:mjsws > 馆藏分类
配色: 字号:
spring security之图片验证码教程
2018-08-28 | 阅:  转:  |  分享 
  
springsecurity之图片验证码教程在登录界面图形添加验证码开发生成图像验证码接口在认证流程中加入图像验证码校验重构代码开发生
成图像验证码接口思路:根据随机数生成图片将随机数存到session中将生成的图片写入响应中这里相当于功能,生成图片什么
的不记录了。网上一大堆,记录下这里的一些代码思路由于是公用的,把该服务写在core中图片验证码信息类?12345678910111
2131415161718192021222324252627282930packagecn.mrcode.imooc.spri
ngsecurity.securitycore.validate.code;?importjava.awt.image.Buff
eredImage;importjava.time.LocalDateTime;?/?图形验证码?@author:
zhuqiang?@version:V1.0?@date:2018/8/322:44?/publiccla
ssImageCode{?privateBufferedImageimage;?privateStringcode;?
privateLocalDateTimeexpireTime;//过期时间??/?@paramimage?@
paramcode?@paramexpireIn过期时间,单位秒?/?publicImageCode(Buffere
dImageimage,Stringcode,intexpireIn){?this.image=image;?th
is.code=code;?this.expireTime=LocalDateTime.now().plusSeconds
(expireIn);?}?//是否过期?publicbooleanisExpried(){returnthis.exp
ireTime.isBefore(LocalDateTime.now());?}验证码服务?1234567891011121314
151617181920212223242526272829packagecn.mrcode.imooc.springsecur
ity.securitycore.validate.code;/?验证码服务金星棋牌http://www.lrnfk.c
om?@author:zhuqiang?@version:V1.0?@date:2018/8/322:4
8?/@RestControllerpublicclassValidateCodeController{?private
staticfinalStringSESSION_KEY="SESSION_KEY_IMAGE_CODE";?//这里
又使用了spring的工具类来操作session?privateSessionStrategysessionStrategy
=newHttpSessionSessionStrategy();??@GetMapping("/code/image")?p
ublicvoidcreateCode(HttpServletRequestrequest,HttpServletResp
onseresponse)throwsIOException{?ImageCodeimageCode=createI
mageCode(request);?sessionStrategy.setAttribute(newServletWebReq
uest(request),SESSION_KEY,imageCode);?response.setContentType("
image/jpeg");?//禁止图像缓存。?response.setHeader("Pragma","no-cache");
?response.setHeader("Cache-Control","no-cache");?ImageIO.write(i
mageCode.getImage(),"JPEG",response.getOutputStream());?}??priv
ateImageCodecreateImageCode(HttpServletRequestrequest)throws
IOException{?Stringcode=RandomStringUtils.randomAlphanumeric(
4);?BufferedImageimage=createImageCode(80,40,code);?returnn
ewImageCode(image,code,60);?}需要把该服务路径在cn.mrcode.imooc.springse
curity.securitybrowser.BrowserSecurityConfig中配置放行。在认证流程中加入图像验证码校
验步骤:由之前的源码的探索发现,只要把过滤器添加到spring现有的过滤器链上就可以了;编写验证码过滤器放在UsernamePa
sswordAuthenticationFilter过滤器之前?123456789101112131415161718192021
22232425262728293031323334353637383940414243444546474849505152535
45556575859606162636465666768697071727374757677packagecn.m
rcode.imooc.springsecurity.securitycore.validate.code;?importorg
.apache.commons.lang3.StringUtils;importorg.springframework.secu
rity.web.authentication.AuthenticationFailureHandler;importorg.s
pringframework.social.connect.web.HttpSessionSessionStrategy;impo
rtorg.springframework.social.connect.web.SessionStrategy;import
org.springframework.web.bind.ServletRequestBindingException;impor
torg.springframework.web.bind.ServletRequestUtils;importorg.spr
ingframework.web.context.request.ServletWebRequest;importorg.spr
ingframework.web.filter.OncePerRequestFilter;?importjavax.servle
t.FilterChain;importjavax.servlet.ServletException;importjavax.
servlet.http.HttpServletRequest;importjavax.servlet.http.HttpSer
vletResponse;importjava.io.IOException;?/?图片验证码验证过滤器?OnceP
erRequestFilterspring提供的,保证在一个请求中只会被调用一次?@author:zhuqiang?
@version:V1.0?@date:2018/8/323:24?/publicclassValidateC
odeFilterextendsOncePerRequestFilter{?//在初始化本类的地方进行注入?//一般在配
置securityhttp的地方进行添加过滤器?privateAuthenticationFailureHandlerfai
lureHandler;?privateSessionStrategysessionStrategy=newHttpSe
ssionSessionStrategy();??@Override?protectedvoiddoFilterInterna
l(HttpServletRequestrequest,HttpServletResponseresponse,Filte
rChainfilterChain)throwsServletException,IOException{?//为登录
请求,并且为post请求?if(StringUtils.equals("/authentication/form",reque
st.getRequestURI())?&&StringUtils.equalsAnyIgnoreCase(request.ge
tMethod(),"post")){try{?validate(request);}catch(ValidateCod
eExceptione){?failureHandler.onAuthenticationFailure(request,r
esponse,e);?return;}?}?filterChain.doFilter(request,response);?
}??privatevoidvalidate(HttpServletRequestrequest)throwsServl
etRequestBindingException{?//拿到之前存储的imageCode信息?ServletWebReque
stswr=newServletWebRequest(request);?ImageCodecodeInSession
=(ImageCode)sessionStrategy.getAttribute(swr,ValidateCodeContr
oller.SESSION_KEY);?//又是一个spring中的工具类,388棋牌http://www.455573.com
?//试问一下,如果不看源码怎么可能知道有这些工具类可用??StringcodeInRequest=ServletRequ
estUtils.getStringParameter(request,"imageCode");??if(StringUti
ls.isBlank(codeInRequest)){thrownewValidateCodeException("验证码的
值不能为空");?}?if(codeInSession==null){thrownewValidateCodeExce
ption("验证码不存在");?}?if(codeInSession.isExpried()){sessionStrateg
y.removeAttribute(swr,ValidateCodeController.SESSION_KEY);throw
newValidateCodeException("验证码已过期");?}?if(!StringUtils.equals(co
deInSession.getCode(),codeInRequest)){thrownewValidateCodeExc
eption("验证码不匹配");?}?sessionStrategy.removeAttribute(swr,Validate
CodeController.SESSION_KEY);?}??publicAuthenticationFailureHandl
ergetFailureHandler(){?returnfailureHandler;?}??publicvoidse
tFailureHandler(AuthenticationFailureHandlerfailureHandler){?th
is.failureHandler=failureHandler;?}}
把过滤器添加到现有认证流程中?12345
6789ValidateCodeFiltervalidateCodeFilter=newValidateCod
eFilter();validateCodeFilter.setFailureHandler(myAuthenticationFa
ilureHandler);http?//由源码得知,在最前面的是UsernamePasswordAuthenticationF
ilter?.addFilterBefore(validateCodeFilter,UsernamePasswordAuthen
ticationFilter.class)?//定义表单登录-身份认证的方式?.formLogin()?.loginPage
("/authentication/require")?.loginProcessingUrl("/authentication/
form")
还需要注意的一个地方就是myAuthenticationFailureHandler中。因为失败会调用这
个处理器;这里和视频中演示的不一样。不会再把异常信息打印到前段页面了。后补:视频中不知道什么时候把LoginType变成了json
类型,所以会抛出异常?12345678910111213if(securityProperties.getBrows
er().getLoginType()==LoginType.JSON){?response.setContentType(
"application/json;charset=UTF-8");?response.setStatus(HttpStatus.
INTERNAL_SERVER_ERROR.value());?response.getWriter().write(object
Mapper.writeValueAsString(exception));}else{?//在这里失败跳转不回去了。而且异
常信息也没有打印出来。父类默认打印了死的一句话天地棋牌http://www.dadiqipaigw.cn?//在这里就不往上面扔了,这里就先当做defaultFailureUrl不存在吧?//模拟打印异常信息?response.setContentType("text/html;charset=UTF-8");?response.sendError(HttpStatus.UNAUTHORIZED.value(),exception.getLocalizedMessage());//super.onAuthenticationFailure(request,response,exception);}
注意:之前我一直在说,异常了但是不会显示,不知道去哪里了。这几次调试发现日志不断访问/error,好像这个在自己设置了BrowserSecurityConfig的拦截放行路径后,就一致这样了
献花(0)
+1
(本文系mjsws首藏)