SpringSecurity实现图形验证码功能实例代码
程序员文章站
2024-02-28 14:22:10
spring security
spring security是一个能够为基于spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在sp...
spring security
spring security是一个能够为基于spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在spring应用上下文中配置的bean,充分利用了spring ioc,di(控制反转inversion of control ,di:dependency injection 依赖注入)和aop(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
本文重点给大家介绍springsecurity实现图形验证码功能,具体内容如下:
1.开发生成图形验证码接口
-> 封装imagecode对象,来存放图片验证码的内容、图片以及有效时间
public class imagecode { private bufferedimage image;// 图片 private string code;// 验证码 private localdatetime expiretime;// 有效时间 public imagecode(bufferedimage image, string code, int expirein) { this.image = image; this.code = code; // 出入一个秒数,自动转为时间,如过期时间为60s,这里的expirein就是60,转换为当前时间上加上这个秒数 this.expiretime = localdatetime.now().plusseconds(expirein); } public imagecode(bufferedimage image, string code, localdatetime expiretime) { this.image = image; this.code = code; this.expiretime = expiretime; } public bufferedimage getimage() { return image; } public void setimage(bufferedimage image) { this.image = image; } public string getcode() { return code; } public void setcode(string code) { this.code = code; } public localdatetime getexpiretime() { return expiretime; } public void setexpiretime(localdatetime expiretime) { this.expiretime = expiretime; } }
-> 写一个controller用于生成图片和校验验证码
public class validatecodecontroller { private static final string session_key = "session_key_image_code"; private sessionstrategy sessionstrategy = new httpsessionsessionstrategy(); @getmapping("/code/image") public void createcode(httpservletrequest request, httpservletresponse response) throws ioexception { // 根据随机数生成图片 imagecode imagecode = createimagecode(request); // 将随机数存到session中 sessionstrategy.setattribute(new servletwebrequest(request), session_key, imagecode); // 将生成的图片写到接口的响应中 imageio.write(imagecode.getimage(), "jpeg", response.getoutputstream()); } private imagecode createimagecode(httpservletrequest request) { // 图片的宽高(像素) int width = 67; int height = 23; // 生成图片对象 bufferedimage image = new bufferedimage(width, height, bufferedimage.type_int_rgb); graphics g = image.getgraphics(); // 生成随机条纹干扰 random random = new random(); g.setcolor(getrandcolor(200, 250)); g.fillrect(0, 0, width, height); g.setfont(new font("times new roman", font.italic, 20)); g.setcolor(getrandcolor(160, 200)); for (int i = 0; i < 155; i++) { int x = random.nextint(width); int y = random.nextint(height); int xl = random.nextint(12); int yl = random.nextint(12); g.drawline(x, y, xl, yl); } // 生成四位随机数 string srand = ""; for (int i = 0; i < 4; i++) { string rand = string.valueof(random.nextint(10)); srand += rand; g.setcolor(new color(20 + random.nextint(110), 20 + random.nextint(110), 20 + random.nextint(110))); g.drawstring(rand, 13 * i + 6, 16); } g.dispose(); // 60秒有效 return new imagecode(image, srand, 60); } /** * 生成随机背景条纹 * @param fc * @param bc * @return */ private color getrandcolor(int fc, int bc) { random random = new random(); if(fc > 255) { fc = 255; } if(bc > 255) { bc = 255; } int r = fc + random.nextint(bc - fc); int g = fc + random.nextint(bc - fc); int b = fc + random.nextint(bc - fc); return new color(r, g, b); } }
第一步:根据随机数生成图片
imagecode imagecode = createimagecode(request);
第二步:将随机数存到session中
sessionstrategy.setattribute(new servletwebrequest(request), session_key, imagecode);
第三步:将生成的图片写到接口的响应中
imageio.write(imagecode.getimage(), “jpeg”, response.getoutputstream());
-> 在静态页面中加入图片验证码的标签
<tr> <td>图形验证码:</td> <td> <input type="text" name="imagecode"> <img src="/code/image"> </td> </tr>
-> 将接口请求地址配进认证
@override protected void configure(httpsecurity http) throws exception { http.formlogin() .loginpage("/authencation/require") .loginprocessingurl("/authentication/form") .successhandler(imoocauthenticationsuccesshandler) .failurehandler(imoocauthenticationfailurehandler) .and() .authorizerequests() .antmatchers("/authencation/require", securitypropertis.getbrowserpropertis().getloginpage(), "/code/image").permitall() // 加入"/code/image"地址 .anyrequest() .authenticated() .and() .csrf().disable(); }
->启动服务器访问静态表单
如图所示:
2.在认证流程中加入图形验证码校验
-> 写一个filter进行拦截 public class validatecodefilter extends onceperrequestfilter{ private authenticationfailurehandler authenticationfailurehandler; private sessionstrategy sessionstrategy = new httpsessionsessionstrategy(); @override protected void dofilterinternal(httpservletrequest request, httpservletresponse response, filterchain filterchain) throws servletexception, ioexception { //如果访问的是/authentication/form并且为post请求 if(stringutils.equals("/authentication/form", request.getrequesturi()) && stringutils.equals(request.getmethod(), "post")) { try { // 验证图片验证码是否填写正确 validate(new servletwebrequest(request)); } catch (validatecodeexception e) { // 抛出异常,并返回,不再访问资源 authenticationfailurehandler.onauthenticationfailure(request, response, e); return; } } // 通过,执行后面的filter filterchain.dofilter(request, response); } // 校验验证码的逻辑 private void validate(servletwebrequest request) throws servletrequestbindingexception { imagecode codeinsession = (imagecode) sessionstrategy.getattribute(request, validatecodecontroller.session_key); string codeinrequest = servletrequestutils.getstringparameter(request.getrequest(), "imagecode"); if(stringutils.isblank(codeinrequest)) { throw new validatecodeexception("验证码的值不能为空"); } if(codeinsession == null){ throw new validatecodeexception("验证码不存在"); } if(codeinsession.isexpried()) { sessionstrategy.removeattribute(request, validatecodecontroller.session_key); throw new validatecodeexception("验证码已过期"); } if(!stringutils.equals(codeinsession.getcode(), codeinrequest)) { throw new validatecodeexception("验证码不匹配"); } sessionstrategy.removeattribute(request, validatecodecontroller.session_key); } public authenticationfailurehandler getauthenticationfailurehandler() { return authenticationfailurehandler; } public void setauthenticationfailurehandler(authenticationfailurehandler authenticationfailurehandler) { this.authenticationfailurehandler = authenticationfailurehandler; } public sessionstrategy getsessionstrategy() { return sessionstrategy; } public void setsessionstrategy(sessionstrategy sessionstrategy) { this.sessionstrategy = sessionstrategy; } }
-> 配置再configure中,生效
@override protected void configure(httpsecurity http) throws exception { // 声明filter validatecodefilter validatecodefilter = new validatecodefilter(); // 配置验证失败执行的handler validatecodefilter.setauthenticationfailurehandler(imoocauthenticationfailurehandler); // 添加filter到认证流程 http.addfilterbefore(validatecodefilter, usernamepasswordauthenticationfilter.class) .formlogin() .loginpage("/authencation/require") .loginprocessingurl("/authentication/form") .successhandler(imoocauthenticationsuccesshandler) .failurehandler(imoocauthenticationfailurehandler) .and() .authorizerequests() .antmatchers("/authencation/require", securitypropertis.getbrowserpropertis().getloginpage(), "/code/image").permitall() .anyrequest() .authenticated() .and() .csrf().disable(); }
至此,图片验证码验证流程已经全部完成。
启动服务,进行测试即可。
上一篇: 浅析Python中的赋值和深浅拷贝
下一篇: Lesson03_02 样式规则选择器