实现验证码
导入依赖
<!--验证码相关的依赖--> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
定义验证码配置类
package Rememberme.config; import com.google.code.kaptcha.Producer; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Properties; /** * 验证码相关配置 */ @Configuration public class KaptchaConfig { @Bean public Producer kaptcha() { Properties properties = new Properties(); properties.setProperty("kaptcha.image.width", "150"); properties.setProperty("kaptcha.image.height", "50"); properties.setProperty("kaptcha.textproducer.char.string", "0123456789"); properties.setProperty("kaptcha.textproducer.char.length", "4"); Config config = new Config(properties); DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); defaultKaptcha.setConfig(config); return defaultKaptcha; } }
定义验证码的拦截器
//自定义验证码Filter public class kaptchaFilter extends UsernamePasswordAuthenticationFilter { }
自定义拦截器配置类,实现UsernamePasswordAuthenticationFilter
然后设置默认的拦截器
//类似源码,定义默认值 public static final String KAPTCHA_KEY = "kaptcha";//默认值 private String kaptcha = KAPTCHA_KEY; 实现拦截器的验证方法attemptAuthentication
@Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { //1. 验证请求判断是否为post if (!request.getMethod().equalsIgnoreCase("post")) { throw new KaptchaNotMatchException("请求异常" + request.getMethod()); } //2.获取验证码 String kaptcha = request.getParameter(getKaptcha()); String sessionKaptcha = (String) request.getSession().getAttribute("kaptcha"); if (!ObjectUtils.isEmpty(kaptcha) && !ObjectUtils.isEmpty(sessionKaptcha) && kaptcha.equalsIgnoreCase(sessionKaptcha)) { //3. 返回自定义的组件 return super.attemptAuthentication(request, response); } throw new KaptchaNotMatchException("验证码异常!"); }
自定义拦截器配置
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public kaptchaFilter KaptchaFilter() throws Exception { kaptchaFilter filter = new kaptchaFilter(); //指定处理登录 filter.setFilterProcessesUrl("/doLogin"); //setUsername、password.... //指定接受拦截器的请求参数名 filter.setKaptcha("kaptcha"); //自定义拦截器的认证管理器 filter.setAuthenticationManager(authenticationManagerBean()); //指定认证成功或者失败的请求 filter.setAuthenticationSuccessHandler((request, response, authentication) -> { Map<String, Object> result = new HashMap<>(); result.put("msg", "登录成功!"); result.put("status", "200"); result.put("用户信息", (User) authentication.getPrincipal()); response.setContentType("application/json;charset=UTF-8"); String s = new ObjectMapper().writeValueAsString(result); response.getWriter().println(s); }); filter.setAuthenticationFailureHandler((request, response, exception) -> { Map<String, Object> result = new HashMap<>(); result.put("msg", "登录失败!!"); result.put("status", "400"); result.put("错误信息", exception.getMessage()); response.setContentType("application/json;charset=UTF-8"); String s = new ObjectMapper().writeValueAsString(result); response.getWriter().println(s); }); return filter; } }
注意点
//指定接受拦截器的请求参数名 filter.setKaptcha("kaptcha"); //自定义拦截器的认证管理器 filter.setAuthenticationManager(authenticationManagerBean());
将自定义的拦截器交给容器
用来将自定义AuthenticationManager在工厂中进行暴露,可以在任何位置注入
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { //用来将自定义AuthenticationManager在工厂中进行暴露,可以在任何位置注入 @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean public kaptchaFilter KaptchaFilter() throws Exception { kaptchaFilter filter = new kaptchaFilter(); //指定处理登录 filter.setFilterProcessesUrl("/doLogin"); //setUsername、password.... //指定接受拦截器的请求参数名 filter.setKaptcha("kaptcha"); //自定义拦截器的认证管理器 filter.setAuthenticationManager(authenticationManagerBean()); //指定认证成功或者失败的请求 filter.setAuthenticationSuccessHandler((request, response, authentication) -> { Map<String, Object> result = new HashMap<>(); result.put("msg", "登录成功!"); result.put("status", "200"); result.put("用户信息", (User) authentication.getPrincipal()); response.setContentType("application/json;charset=UTF-8"); String s = new ObjectMapper().writeValueAsString(result); response.getWriter().println(s); }); filter.setAuthenticationFailureHandler((request, response, exception) -> { Map<String, Object> result = new HashMap<>(); result.put("msg", "登录失败!!"); result.put("status", "400"); result.put("错误信息", exception.getMessage()); response.setContentType("application/json;charset=UTF-8"); String s = new ObjectMapper().writeValueAsString(result); response.getWriter().println(s); }); return filter; } }
替换自己的拦截器
//替换默认拦截器 http.addFilterAt(KaptchaFilter(), UsernamePasswordAuthenticationFilter.class);
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .mvcMatchers("/index").permitAll() .mvcMatchers("/loginPages").permitAll() .mvcMatchers("/vc.jpg").permitAll() //放行验证码的请求 .anyRequest().authenticated() .and() .formLogin() .loginPage("/loginPages") // .loginProcessingUrl("/doLogin") // .defaultSuccessUrl("/index") // .failureUrl("/loginPage") // .and() // .logout() // .logoutSuccessUrl("/index") .and() .csrf().disable(); //替换默认拦截器 http.addFilterAt(KaptchaFilter(), UsernamePasswordAuthenticationFilter.class); } }
controller配置验证码拦截器发送的请求
@RequestMapping("/vc.jpg") public void Kaptcha(HttpServletResponse response, HttpSession session) throws IOException { response.setContentType("image/png"); String text = producer.createText(); session.setAttribute("kaptcha", text); BufferedImage image = producer.createImage(text); ServletOutputStream stream = response.getOutputStream(); ImageIO.write(image, "jpg", stream); }
前端实现请求接口
验证码: <input name="kaptcha" type="text"/> <img alt="" th:src="@{/vc.jpg}"><br>