Spring Security 图形验证码

图形验证码

自定义过滤器

相关代码如下

  • 获取图片验证码
@Controller
public class CaptchaController {



    @Autowired
    private Producer producer;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    /**
     * 生成图片验证码
     * @throws IOException
     */
    @GetMapping("/getCaptcha.jpg")
    public  void getCaptcha() throws IOException {

        //生成文本内容
        String capText=producer.createText();
        request.getSession().removeAttribute("captcha");
        //将图片输出给浏览器
        response.setContentType("image/jpeg");
        //保存到session里面
        request.getSession().setAttribute("captcha",capText);
        //生成图片
        BufferedImage image = producer.createImage(capText);
        try(ServletOutputStream outputStream = response.getOutputStream()) {
            ImageIO.write(image,"jpeg",outputStream);
        }catch (Exception e){
          throw  e;
        }

    }


}

  • kaptcha 配置
@Configuration
public class CaptchaConfig {


    @Bean
    public Producer producer(){
        //kaptcha 配置
        Properties properties = new Properties();
        //图片宽度
        properties.setProperty("kaptcha.image.width","100");
        //图片长度
        properties.setProperty("kaptcha.image.height","40");
        //字符集
        properties.setProperty("kaptcha.textproducer.char.string","abc0123456789");
        //字符长度
        properties.setProperty("kaptcha.textproducer.char.length","4");
        //使用默认的图形验证码
        DefaultKaptcha kaptcha = new DefaultKaptcha();
        Config config=new Config(properties);
        kaptcha.setConfig(config);
        return kaptcha;
    }
}
  • Security配置

@EnableWebSecurity
@Configuration
public class SecurityCaptchaConfig extends WebSecurityConfigurerAdapter {

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/getCaptcha.jpg")
                .permitAll().anyRequest().authenticated().and()
                .formLogin().loginPage("/myLogin.html").
                loginProcessingUrl("/login").failureHandler(myAuthenticationFailureHandler()).permitAll().and().
                 addFilterBefore(verificationCodeFilter(), UsernamePasswordAuthenticationFilter.class).
               csrf().disable();
    }

    @Bean
    public VerificationCodeFilter verificationCodeFilter(){
        return new VerificationCodeFilter();
    }

    @Bean
    public MyAuthenticationFailureHandler myAuthenticationFailureHandler() {
        return new MyAuthenticationFailureHandler();
    }  
}

  • 校验验证码过滤器
public class VerificationCodeFilter  extends OncePerRequestFilter {

    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler ;


    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        //非登陆请求不校验验证码
        if("/login".equals(httpServletRequest.getRequestURI())){
            try {
                verifyCode(httpServletRequest);
                filterChain.doFilter(httpServletRequest,httpServletResponse);
            }catch (VerificationCodeException e){
                authenticationFailureHandler.onAuthenticationFailure(httpServletRequest,httpServletResponse,e);
            }
        }else{
            filterChain.doFilter(httpServletRequest,httpServletResponse);
        }



    }

    public void verifyCode(HttpServletRequest request) throws VerificationCodeException{
        String requestCode= request.getParameter("captcha");
        HttpSession session = request.getSession();
        String sessionCode = (String)session.getAttribute("captcha");
        System.out.println("sessionCode:"+sessionCode+"requestCode:"+requestCode);
        if(!StringUtils.isEmpty(sessionCode)){
            //每次调用登陆请求都刷新验证码
            session.removeAttribute("captcha");
        }

        //校验不通过抛出异常
        if(StringUtils.isEmpty((requestCode))||StringUtils.isEmpty(sessionCode)||!requestCode.equals(sessionCode)){
            throw new VerificationCodeException();
        }

    }


}

  • 自定义验证码异常类
public class VerificationCodeException extends AuthenticationException {

            public VerificationCodeException(){
                super("图形验证码校验失败");
            }
}

  • 异常处理
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {


    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out=response.getWriter();
        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("code","1001");
        if(e instanceof VerificationCodeException){
            resultMap.put("code","1002");
            resultMap.put("msg",e.getMessage());
        }
        resultMap.put("msg",e.getMessage());
        out.write(JSON.toJSONString(resultMap));
    }



}
  • Html
<!DOCTYPE html>
<html lang="en">
  <head>
     <meta charset="UTF-8">
     <title>Title</title>
  </head>
  <body>

<div>
 <form action="login" method="post">
   <table>
    <tr>
        <td>用户名:<input type="text" name="username"/></td>
    </tr>

    <tr>
        <td>密码:<input type="password" name="password"/></td>
    </tr>
     <tr>
         <td> <input type="text" name="captcha" placeholder="captcha" />
             <img src="/getCaptcha.jpg" alt="captcha"  style="margin-left: 20px;"></td>
     </tr>

    <tr>
        <td colspan="2">
            <button type="submit">登录</button>
        </td>
    </tr>
   </table>
  </form>
</div>
</body>
</html>

<style>

    div{
        width: 400px;
        height: 400px;
        margin: 0 auto;
    }
</style>
  • 前端界面
    在这里插入图片描述
    当我们输入错误的验证码时:
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值