结合开源软件kaptcha讲解登陆验证码功能的实现

file

1、验证码生成之配置使用kaptcha

使用google开源的验证码实现类库kaptcha,经过maven坐标引入前端

<dependency>
   <groupId>com.github.penggle</groupId>
   <artifactId>kaptcha</artifactId>
   <version>2.3.2</version>
   <exclusions>
      <exclusion>
         <artifactId>javax.servlet-api</artifactId>
         <groupId>javax.servlet</groupId>
      </exclusion>
   </exclusions>
</dependency>
  • 假设咱们的配置文件是application.yml,新建一个单独的文件叫作kaptcha.properties。由于kaptcha的配置不符合yaml的规范格式,因此只能采用properties。需配合注解PropertySourc使用。
  • 假设咱们的配置文件是application.properties,将下面这段代码加入进去便可,不用单独创建文件。
  • 下面的验证码配置,从英文单词的角度很容易理解,当咱们须要调整验证码的边框、颜色、大小、字体等属性的时候,能够修改这些配置。
kaptcha.border=no
kaptcha.border.color=105,179,90
kaptcha.image.width=100
kaptcha.image.height=45
kaptcha.session.key=code
kaptcha.textproducer.font.color=blue
kaptcha.textproducer.font.size=35
kaptcha.textproducer.char.length=4
kaptcha.textproducer.font.names=宋体,楷体,微软雅黑

下面的代码加载了配置文件中的kaptcha配置(参考Spring Boot的配置加载),若是是独立的properties文件,需加上PropertySource注解说明。
另外,咱们经过加载完成的配置,初始化captchaProducer的Spring Bean,用于生成验证码。java

@Component
@PropertySource(value = {"classpath:kaptcha.properties"})
public class CaptchaConfig {

    @Value("${kaptcha.border}")
    private String border;
    @Value("${kaptcha.border.color}")
    private String borderColor;
    @Value("${kaptcha.textproducer.font.color}")
    private String fontColor;
    @Value("${kaptcha.image.width}")
    private String imageWidth;
    @Value("${kaptcha.image.height}")
    private String imageHeight;
    @Value("${kaptcha.session.key}")
    private String sessionKey;
    @Value("${kaptcha.textproducer.char.length}")
    private String charLength;
    @Value("${kaptcha.textproducer.font.names}")
    private String fontNames;
    @Value("${kaptcha.textproducer.font.size}")
    private String fontSize;

    @Bean(name = "captchaProducer")
    public DefaultKaptcha getKaptchaBean() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty("kaptcha.border", border);
        properties.setProperty("kaptcha.border.color", borderColor);
        properties.setProperty("kaptcha.textproducer.font.color", fontColor);
        properties.setProperty("kaptcha.image.width", imageWidth);
        properties.setProperty("kaptcha.image.height", imageHeight);
        properties.setProperty("kaptcha.session.key", sessionKey);
        properties.setProperty("kaptcha.textproducer.char.length", charLength);
        properties.setProperty("kaptcha.textproducer.font.names", fontNames);
        properties.setProperty("kaptcha.textproducer.font.size",fontSize);
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }

}

至此,Kaptcha开源验证码软件的配置咱们就完成了,若是发现IDEA环境下配置文件读取中文乱码,修改以下配置。
git

2、验证码生成之session保存

生成验证码的Controller。同时须要开放路径"/kaptcha"的访问权限,配置成不需登陆也无需任何权限便可访问的路径。如何进行配置,笔者以前的文章已经讲过了。github

  • 经过captchaProducer.createText()生成验证码文字,并和失效时间一块儿保存到CaptchaImageVO中。
  • 将CaptchaImageVO验证码信息类对象,保存到session中。(这个类的代码后文有介绍)
  • 经过captchaProducer.createImage(capText)生成验证码图片,并经过ServletOutputStream返回给前端
@RestController
public class CaptchaController {

    @Resource
    DefaultKaptcha captchaProducer;

    /**
     * 获取验证码
     */
    @RequestMapping(value = "/kaptcha", method = RequestMethod.GET)
    public void kaptcha(HttpSession session, HttpServletResponse response) throws Exception {

        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");

        String capText = captchaProducer.createText();
        CaptchaImageVO captchaImageVO = new CaptchaImageVO(capText,2 * 60);
        //将验证码存到session
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, captchaImageVO);

        //将图片返回给前端
        try(ServletOutputStream out = response.getOutputStream();) {
            BufferedImage bi = captchaProducer.createImage(capText);
            ImageIO.write(bi, "jpg", out);
            out.flush();
        }//使用try-with-resources不用手动关闭流
    }

}

咱们要把CaptchaImageVO保存到session里面。因此该类中不要加图片,只保存验证码文字和失效时间,用于后续验证便可。把验证码图片保存起来既没有用处,又浪费内存。spring

@Data
public class CaptchaImageVO {

    //验证码文字
    private String code;
    //验证码失效时间
    private LocalDateTime expireTime;
 
    public CaptchaImageVO(String code, int expireAfterSeconds){
        this.code = code;
        this.expireTime = LocalDateTime.now().plusSeconds(expireAfterSeconds);
    }
 
    //验证码是否失效
    public boolean isExpried() {
        return LocalDateTime.now().isAfter(expireTime);
    }
 
}

3、验证码用户访问

把以下代码加入到登陆页面合适的位置,注意图片img标签放到登陆表单中。api

<img src="/kaptcha" id="kaptcha" width="110px" height="40px"/>

<script>
    window.onload=function(){
        var kaptchaImg = document.getElementById("kaptcha");
        kaptchaImg.onclick = function(){
            kaptchaImg.src = "/kaptcha?" + Math.floor(Math.random() * 100)
        }
    }
</script>
  • 实现的效果是,页面初始化即加载验证码。之后每一次点击,都会更新验证码。
  • 注意:必定设置width和height,不然图片没法显示。

4、验证码之安全校验

  • 编写咱们的自定义图片验证码过滤器VerificationCodeFilter,过滤器中拦截登陆请求
  • VerificationCodeFilter过滤器中从seesion获取验证码文字与用户输入比对,比对经过执行其余过滤器链
  • 比对不经过,自定义一个异常,交给AuthenticationFailureHandler处理
  • 最后将VerificationCodeFilter放在UsernamePasswordAuthenticationFilter表单过滤器以前执行。

以上是在Spring Security实现登陆验证码验证的逻辑。若是你是使用的shiro或者其余的自定义的登陆验证明现,那就更简单了。就在你的登陆验证的controller里面取出session比对验证码便可,不须要自定义过滤器。安全

期待您的关注

相关文章
相关标签/搜索