SpringSecurity实现图形验证码功能实例代码

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();
}

至此,图片验证码验证流程已经全部完成。

启动服务,进行测试即可。

(0)

相关推荐

  • Spring Security OAuth2集成短信验证码登录以及第三方登录

    前言 基于SpringCloud做微服务架构分布式系统时,OAuth2.0作为认证的业内标准,Spring Security OAuth2也提供了全套的解决方案来支持在Spring Cloud/Spring Boot环境下使用OAuth2.0,提供了开箱即用的组件.但是在开发过程中我们会发现由于Spring Security OAuth2的组件特别全面,这样就导致了扩展很不方便或者说是不太容易直指定扩展的方案,例如: 图片验证码登录 短信验证码登录 微信小程序登录 第三方系统登录 CAS单点登录

  • Spring Security登录添加验证码的实现过程

    登录添加验证码是一个非常常见的需求,网上也有非常成熟的解决方案,其实,要是自己自定义登录实现这个并不难,但是如果需要在 Spring Security 框架中实现这个功能,还得稍费一点功夫,本文就和小伙伴来分享下在 Spring Security 框架中如何添加验证码. 关于 Spring Security 基本配置,这里就不再多说,小伙伴有不懂的可以参考我的书<SpringBoot+Vue全栈开发实战>,本文主要来看如何加入验证码功能. 准备验证码 要有验证码,首先得先准备好验证码,本文采用

  • Spring Security Oauth2.0 实现短信验证码登录示例

    本文介绍了Spring Security Oauth2.0 实现短信验证码登录示例,分享给大家,具体如下: 定义手机号登录令牌 /** * @author lengleng * @date 2018/1/9 * 手机号登录令牌 */ public class MobileAuthenticationToken extends AbstractAuthenticationToken { private static final long serialVersionUID = SpringSecur

  • Spring Security 图片验证码功能的实例代码

    验证码逻辑 以前在项目中也做过验证码,生成验证码的代码网上有很多,也有一些第三方的jar包也可以生成漂亮的验证码.验证码逻辑很简单,就是在登录页放一个image标签,src指向一个controller,这个Controller返回把生成的图片以输出流返回给页面,生成图片的同时把图片上的文本放在session,登录的时候带过来输入的验证码,从session中取出,两者对比.这位老师讲的用Spring Security集成验证码,大体思路和我说的一样,但更加规范和通用些. spring securi

  • SpringBoot结合SpringSecurity实现图形验证码功能

    本文介绍了SpringBoot结合SpringSecurity实现图形验证码功能,分享给大家,具体如下: 生成图形验证码 根据随机数生成图片 将随机数存到Session中 将生成的图片写到接口的响应中 生成图形验证码的过程比较简单,和SpringSecurity也没有什么关系.所以就直接贴出代码了 根据随机数生成图片 /** * 生成图形验证码 * @param request * @return */ private ImageCode generate(ServletWebRequest r

  • SpringBoot+Security 发送短信验证码的实现

    在core模块下properties包中创建SmsCodeProperties 在ValidateCodeProperties中new一个SmsCodeProperties对象,并实现getter.setter方法 在core模块下validate包中创建SmsCodeGenerator实现ValidateCodeGenerator接口 创建SmsCodeSender接口,定义发送短信的抽象方法 实现SmsCodeSender接口 在ValidateCodeBeanConfig中把SmsCode

  • SpringBoot + SpringSecurity 短信验证码登录功能实现

    实现原理 在之前的文章中,我们介绍了普通的帐号密码登录的方式: SpringBoot + Spring Security 基本使用及个性化登录配置. 但是现在还有一种常见的方式,就是直接通过手机短信验证码登录,这里就需要自己来做一些额外的工作了. 对SpringSecurity认证流程详解有一定了解的都知道,在帐号密码认证的过程中,涉及到了以下几个类:UsernamePasswordAuthenticationFilter(用于请求参数获取),UsernamePasswordAuthentica

  • SpringSecurity实现图形验证码功能实例代码

    Spring Security Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作. 本文重点给大家介绍Spri

  • AngularJS 实现点击按钮获取验证码功能实例代码

    html :样式采用了sui框架的样式,请自行引入查看,AngularJS,自己引入, <div ng-controller="forGetPassword" ng-app="routingDemoApp"> <form novalidate name="forget"> <header class="bar bar-nav"> <a href="javascript:his

  • Web制作验证码功能实例代码

    web开发中,经常会使用验证码功能,例如登录.注册,或其他关键功能之前经常会使用.合理使用 验证功能可以防止ddos攻击.爬虫攻击等.   实现效果:   实现原理: 由后台提供生成验证码的接口,前端每次请求会后端会生成验证码图片和验证码,验证码图片发送到客户端供客户端显示, 验证码字符串保存再后端的Session中,待前端再次请求业务接口与session里的验证码字符串做比对.    实现思路: 1.先由后端提供可以生产验证码图片的接口 2.前端通过 img 中设置 src 属性,请求验证码生

  • Java生成验证码功能实例代码

    页面上输入验证码是比较常见的一个功能,实现起来也很简单.给大家写一个简单的生成验证码的示例程序,需要的朋友可以借鉴一下. 闲话少续,直接上代码.代码中的注释很详细. package com.SM_test.utils; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import ja

  • Java实现随机验证码功能实例代码

    现在许多系统的注册.登录或者发布信息模块都添加的随机码功能,就是为了避免自动注册程序或者自动发布程序的使用.验证码实际上就是随机选择一些字符以图片的形式展现在页面上,如果进行番茄花园xp系统下载提交操作的同时需要将图片上的字符同时提交,如果提交的字符与服务器session保存的不同,则认为提交信息无效.为了避免自动程序分析解析图片,通常会在图片上随机生成一些干扰线或者将字符进行扭曲,增加自动识别的难度. 复制代码 代码如下: package com.servlet;import java.awt

  • ASP.NET中画图形验证码的实现代码

    本文给大家分享一段asp.net代码实现画图形验证码功能,代码简单易懂,具体代码如下所示: context.Response.ContentType = "image/jpeg"; //生成随机的中文验证码 string yzm = "人口手大小多少上中下男女天地会反清复明杨中科小宝双儿命名空间语现在明天来多个的我山东河北南固安北京南昌东海西安是沙河高教园学" + "木禾上下土个八入大天人火文六七儿九无口日中了子门月不开四五目耳头米见白田电也长山出飞马鸟云

  • Ajax+Struts2实现验证码验证功能实例代码

    众所周知,验证码在我们的生活中都是非常常见的,很多公司都在各种折腾各种各样的验证码,这里简要的用一个小案例来实现验证码的功能(ps:其实我挺讨厌验证码这个东西的). 今天分享的是通过ajax来动态的验证验证码输入是否正确.我们这里采用的是ajax+struts2来做的这个验证. 我们新建一个web工程.然后需要导入struts的相应包.之后我们需要写一个类来生成验证码. 这里命名为01_image.jsp,这类的主要功能就是生成验证码,里面是各种画线条,随机数字等,我这里设置的是5个数字的验证,

  • Android仿滴滴出行验证码输入框功能实例代码

    最近公司项目中有一个类似滴滴出行填写验证码的弹框,下面是我撸出来的效果: 中间的那个输入密码的6个框框其实就是用shape画的背景,通过监听EditText获取焦点来改变背景,废话少说,直接上代码吧. 2.效果实现 代码内容比较简单,所以大家可以直接看代码 VerificationCodeInput.java /** * @author hydCoder * @date 2017/9/22 14:39 * @desc 输入验证码的自定义view * @email hyd_coder@163.co

  • PHP实现生成带背景的图形验证码功能

    本文实例讲述了PHP实现生成带背景的图形验证码功能.分享给大家供大家参考,具体如下: 以前我们利用php生成的都是无背景或同一色彩背景的验证码了,但这种验证容易给机器识别了,这里就来介绍一些生成带背景的图形验证码实例. 1.产生一张png的图片, 2.为图片设置背景色, 3.设置字体颜色和样式, 4.产生4位数的随机的验证码, 5.把产生的每个字符调整旋转角度和位置画到png图片上, 6.加入噪点和干扰线防止注册机器分析原图片来恶意注册, 7.输出图片, 8.释放图片所占内存 authcode.

随机推荐