SpringSecurity添加图形验证码认证功能
第一步:图形验证码接口
1.使用第三方的验证码生成工具Kaptcha
@Configuration
public class KaptchaImageCodeConfig {
    @Bean
    public DefaultKaptcha getDefaultKaptcha(){
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty(Constants.KAPTCHA_BORDER, "yes");
        properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "192,192,192");
        properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "110");
        properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "36");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "28");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "宋体");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
		// 图片效果
        properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL,
                "com.google.code.kaptcha.impl.ShadowGimpy");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}
2.设置验证接口
Logger logger = LoggerFactory.getLogger(getClass());
public static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";
@GetMapping("/code/image")
public void codeImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 获得随机验证码
    String code = defaultKaptcha.createText();
    logger.info("验证码:{}",code);
    // 将验证码存入session
    request.getSession().setAttribute(SESSION_KEY,code);
    // 绘制验证码
    BufferedImage image = defaultKaptcha.createImage(code);
    // 输出验证码
    ServletOutputStream out = response.getOutputStream();
    ImageIO.write(image, "jpg", out);
}
3.模板表单设置
<div class="form-group">
    <label>验证码:</label>
    <input type="text" class="form-control" placeholder="验证码" name="code">
    <img src="/code/image" th:src="@{/code/image}" onclick="this.src='/code/image?'+Math.random()">
</div>
第二步:设置图像验证过滤器
1.过滤器
@Component
public class ImageCodeValidateFilter extends OncePerRequestFilter {
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    // 失败处理器
    @Resource
    public void setMyAuthenticationFailureHandler(MyAuthenticationFailureHandler myAuthenticationFailureHandler) {
        this.myAuthenticationFailureHandler = myAuthenticationFailureHandler;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            if ("/login/form".equals(request.getRequestURI()) &&
                    request.getMethod().equalsIgnoreCase("post")) {
                // 获取session的验证码
                String sessionCode = (String) request.getSession().getAttribute(PageController.SESSION_KEY);
                // 获取用户输入的验证码
                String inputCode = request.getParameter("code");
                // 判断是否正确
                if(sessionCode == null||!sessionCode.equals(inputCode)){
                    throw new ValidateCodeException("验证码错误");
                }
            }
        }catch (AuthenticationException e){
            myAuthenticationFailureHandler.onAuthenticationFailure(request,response,e);
            //e.printStackTrace();
            return;
        }
        filterChain.doFilter(request, response);
    }
}
异常类
public class ValidateCodeException extends AuthenticationException {
    public ValidateCodeException(String msg) {
        super(msg);
    }
}
注意:一定是继承AuthenticationException
第三步:将图像验证过滤器添加到springsecurity过滤器链中
1.添加到过滤器链中,并设置在用户认证过滤器(UsernamePasswordAuthenticationFilter)前
@Resource
private ImageCodeValidateFilter imageCodeValidateFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
    // 前后代码略
    // 添加图形验证码过滤器链
    http.addFilterBefore(imageCodeValidateFilter, UsernamePasswordAuthenticationFilter.class)
}
2.一定不要忘记放行验证码接口
// 拦截设置
http
    .authorizeHttpRequests()
    //排除/login
    .antMatchers("/login","/code/image").permitAll();
```# SpringSecurity添加图形验证码认证功能
## 第一步:图形验证码接口
### 1.使用第三方的验证码生成工具==Kaptcha==
> [https://github.com/penggle/kaptcha](https://github.com/penggle/kaptcha)
```java
@Configuration
public class KaptchaImageCodeConfig {
    @Bean
    public DefaultKaptcha getDefaultKaptcha(){
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty(Constants.KAPTCHA_BORDER, "yes");
        properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "192,192,192");
        properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "110");
        properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "36");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "28");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "宋体");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
		// 图片效果
        properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL,
                "com.google.code.kaptcha.impl.ShadowGimpy");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}
2.设置验证接口
Logger logger = LoggerFactory.getLogger(getClass());
public static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";
@GetMapping("/code/image")
public void codeImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
    // 获得随机验证码
    String code = defaultKaptcha.createText();
    logger.info("验证码:{}",code);
    // 将验证码存入session
    request.getSession().setAttribute(SESSION_KEY,code);
    // 绘制验证码
    BufferedImage image = defaultKaptcha.createImage(code);
    // 输出验证码
    ServletOutputStream out = response.getOutputStream();
    ImageIO.write(image, "jpg", out);
}
3.模板表单设置
<div class="form-group">
    <label>验证码:</label>
    <input type="text" class="form-control" placeholder="验证码" name="code">
    <img src="/code/image" th:src="@{/code/image}" onclick="this.src='/code/image?'+Math.random()">
</div>
第二步:设置图像验证过滤器
1.过滤器
@Component
public class ImageCodeValidateFilter extends OncePerRequestFilter {
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    // 失败处理器
    @Resource
    public void setMyAuthenticationFailureHandler(MyAuthenticationFailureHandler myAuthenticationFailureHandler) {
        this.myAuthenticationFailureHandler = myAuthenticationFailureHandler;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            if ("/login/form".equals(request.getRequestURI()) &&
                    request.getMethod().equalsIgnoreCase("post")) {
                // 获取session的验证码
                String sessionCode = (String) request.getSession().getAttribute(PageController.SESSION_KEY);
                // 获取用户输入的验证码
                String inputCode = request.getParameter("code");
                // 判断是否正确
                if(sessionCode == null||!sessionCode.equals(inputCode)){
                    throw new ValidateCodeException("验证码错误");
                }
            }
        }catch (AuthenticationException e){
            myAuthenticationFailureHandler.onAuthenticationFailure(request,response,e);
            //e.printStackTrace();
            return;
        }
        filterChain.doFilter(request, response);
    }
}
异常类
public class ValidateCodeException extends AuthenticationException {
    public ValidateCodeException(String msg) {
        super(msg);
    }
}
注意:一定是继承AuthenticationException
第三步:将图像验证过滤器添加到springsecurity过滤器链中
1.添加到过滤器链中,并设置在用户认证过滤器(UsernamePasswordAuthenticationFilter)前
@Resource
private ImageCodeValidateFilter imageCodeValidateFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
    // 前后代码略
    // 添加图形验证码过滤器链
    http.addFilterBefore(imageCodeValidateFilter, UsernamePasswordAuthenticationFilter.class)
}
2.一定不要忘记放行验证码接口
// 拦截设置
http
    .authorizeHttpRequests()
    //排除/login
    .antMatchers("/login","/code/image").permitAll();










