登录输入随机验证码功能也是比价基础的功能 spring security组成就是一大串过滤器链 首先过滤用户是否正确 然后过滤状态是否可用等,那么验证码就是在用户过滤器前再加入一个过滤器 如果验证码不正确直接返回
KaptchaImageCodeConfig
验证码样式
@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; } }
SpringSecurityConfig
http.addFilterBefore(imageCodeValidateFilter, UsernamePasswordAuthenticationFilter.class) 将验证码过滤器链添加到用户过滤器之前。
@EnableWebSecurity public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { /** * 验证码过滤器 */ @Autowired private ImageCodeValidateFilter imageCodeValidateFilter; @Override protected void configure(HttpSecurity http) throws Exception { // 验证码过滤器 http.addFilterBefore(imageCodeValidateFilter, UsernamePasswordAuthenticationFilter.class) // 跳转前台的地址 .formLogin().loginPage("/loginPage") // 登录调用的接口地址 .loginProcessingUrl("/login").successHandler(customAuthenticationSuccessHandler); } }
ImageCodeValidateFilter
验证码过滤器
@Component("imageCodeValidateFilter") public class ImageCodeValidateFilter extends OncePerRequestFilter { @Autowired SecurityProperties securityProperties; @Autowired CustomAuthenticationFailureHandler customAuthenticationFailureHandler; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 1. 如果是post方式 的登录请求,则校验输入的验证码是否正确 if ("/login".equals(request.getRequestURI()) && request.getMethod().equalsIgnoreCase("post")) { try { // 校验验证码合法性 validate(request); } catch (AuthenticationException e) { // 交给失败处理器进行处理异常 也就是上文失败返回的json customAuthenticationFailureHandler.onAuthenticationFailure(request, response, e); // 一定要记得结束 return; } } // 放行请求 往下执行过滤器 filterChain.doFilter(request, response); } private void validate(HttpServletRequest request) { // 先获取seesion中的验证码 String sessionCode = (String)request.getSession().getAttribute(CODE_SESSION_KEY); // 获取用户输入的验证码 String inpuCode = request.getParameter("code"); // 判断是否正确 if (StringUtils.isBlank(inpuCode)) { throw new ValidateCodeException("验证码不能为空"); } if (!inpuCode.equalsIgnoreCase(sessionCode)) { throw new ValidateCodeException("验证码输入错误"); } } }
CodeController
获取验证按接口
@Controller public class CodeController { Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private DefaultKaptcha defaultKaptcha; @RequestMapping("/code/image") public void imageCode(HttpServletRequest request, HttpServletResponse response) throws IOException { // 1. 获取验证码字符串 String code = defaultKaptcha.createText(); logger.info("生成的图形验证码是:" + code); // 2. 字符串把它放到session中 request.getSession().setAttribute(CODE_SESSION_KEY, code); // 3. 获取验证码图片 BufferedImage image = defaultKaptcha.createImage(code); // 4. 将验证码图片把它写出去 ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, "jpg", out); } }