Spring|Spring Security添加验证码的两种方式小结

目录

  • 一、自定义认证逻辑
  • 二、自定义过滤器
  • 总结

一、自定义认证逻辑
生成验证码工具
com.github.pengglekaptcha2.3.2

添加Kaptcha配置
@Configurationpublic class KaptchaConfig {@BeanProducer 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; }}

生成验证码文本,放入HttpSession中
根据验证码文本生成图片 通过IO流写出到前端。
@RestControllerpublic class LoginController {@AutowiredProducer producer; @GetMapping("/vc.jpg")public void getVerifyCode(HttpServletResponse resp, HttpSession session) throws IOException {resp.setContentType("image/jpeg"); String text = producer.createText(); session.setAttribute("kaptcha", text); BufferedImage image = producer.createImage(text); try(ServletOutputStream out = resp.getOutputStream()) {ImageIO.write(image, "jpg", out); }}@RequestMapping("/index")public String index() {return "login success"; }@RequestMapping("/hello")public String hello() {return "hello spring security"; }}

form表单
登录 - 锐客网#login .container #login-row #login-column #login-box {border: 1px solid #9C9C9C; background-color: #EAEAEA; }
登录



Spring|Spring Security添加验证码的两种方式小结
文章图片

验证码图片地址为我们在Controller中定义的验证码接口地址。
身份认证是AuthenticationProvider的authenticate方法完成,因此验证码可以在此之前完成:
public class KaptchaAuthenticationProvider extends DaoAuthenticationProvider {@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String kaptcha = req.getParameter("kaptcha"); String sessionKaptcha = (String) req.getSession().getAttribute("kaptcha"); if (kaptcha != null && sessionKaptcha != null && kaptcha.equalsIgnoreCase(sessionKaptcha)) {return super.authenticate(authentication); }throw new AuthenticationServiceException("验证码输入错误"); }}

配置AuthenticationManager:
@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {@BeanAuthenticationProvider kaptchaAuthenticationProvider() {InMemoryUserDetailsManager users = new InMemoryUserDetailsManager(User.builder().username("xiepanapn").password("{noop}123").roles("admin").build()); KaptchaAuthenticationProvider provider = new KaptchaAuthenticationProvider(); provider.setUserDetailsService(users); return provider; }@Override@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {ProviderManager manager = new ProviderManager(kaptchaAuthenticationProvider()); return manager; }@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/vc.jpg").permitAll().anyRequest().authenticated().and().formLogin().loginPage("/mylogin.html").loginProcessingUrl("/doLogin").defaultSuccessUrl("/index.html").failureForwardUrl("/mylogin.html").usernameParameter("uname").passwordParameter("passwd").permitAll().and().csrf().disable(); }}

  1. 配置UserDetailsService提供的数据源
  2. 提供AuthenticationProvider实例并配置UserDetailsService
  3. 重写authenticationManagerBean方法提供一个自己的ProviderManager并自定义AuthenticationManager实例。

二、自定义过滤器
LoginFilter继承UsernamePasswordAuthenticationFilter 重写attemptAuthentication方法:
public class LoginFilter extends UsernamePasswordAuthenticationFilter {@Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {if (!request.getMethod().equals("POST")) {throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); }String kaptcha = request.getParameter("kaptcha"); String sessionKaptcha = (String) request.getSession().getAttribute("kaptcha"); if (!StringUtils.isEmpty(kaptcha) && !StringUtils.isEmpty(sessionKaptcha) && kaptcha.equalsIgnoreCase(sessionKaptcha)) {return super.attemptAuthentication(request, response); }throw new AuthenticationServiceException("验证码输入错误"); }}

在SecurityConfig中配置LoginFilter
@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(AuthenticationManagerBuilder auth)throws Exception {auth.inMemoryAuthentication().withUser("javaboy").password("{noop}123").roles("admin"); }@Override@Beanpublic AuthenticationManager authenticationManagerBean()throws Exception {return super.authenticationManagerBean(); }@BeanLoginFilter loginFilter() throws Exception {LoginFilter loginFilter = new LoginFilter(); loginFilter.setFilterProcessesUrl("/doLogin"); loginFilter.setAuthenticationManager(authenticationManagerBean()); loginFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/hello")); loginFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/mylogin.html")); return loginFilter; }@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/vc.jpg").permitAll().anyRequest().authenticated().and().formLogin().loginPage("/mylogin.html").permitAll().and().csrf().disable(); http.addFilterAt(loginFilter(),UsernamePasswordAuthenticationFilter.class); }}

显然第二种比较简单

总结 【Spring|Spring Security添加验证码的两种方式小结】到此这篇关于Spring Security添加验证码的两种方式的文章就介绍到这了,更多相关Spring Security添加验证码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    推荐阅读