登录输入随机验证码功能也是比价基础的功能 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);
}
}