千家信息网

Spring Security添加验证码的方式有哪些

发表于:2025-01-18 作者:千家信息网编辑
千家信息网最后更新 2025年01月18日,这篇文章主要介绍"Spring Security添加验证码的方式有哪些",在日常操作中,相信很多人在Spring Security添加验证码的方式有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好
千家信息网最后更新 2025年01月18日Spring Security添加验证码的方式有哪些

这篇文章主要介绍"Spring Security添加验证码的方式有哪些",在日常操作中,相信很多人在Spring Security添加验证码的方式有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Spring Security添加验证码的方式有哪些"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

目录
  • 一、自定义认证逻辑

  • 二、自定义过滤器

一、自定义认证逻辑

生成验证码工具

    com.github.penggle    kaptcha    2.3.2

添加Kaptcha配置

@Configurationpublic class KaptchaConfig {    @Bean    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;    }}

生成验证码文本,放入HttpSession中

根据验证码文本生成图片 通过IO流写出到前端。

@RestControllerpublic class LoginController {    @Autowired    Producer 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表单

        登录            

登录




验证码图片地址为我们在Controller中定义的验证码接口地址。

身份认证是AuthenticationProvider的authenticate方法完成,因此验证码可以在此之前完成:

public class KaptchaAuthenticationProvider extends DaoAuthenticationProvider {    @Override    public 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 {    @Bean    AuthenticationProvider 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    @Bean    public AuthenticationManager authenticationManagerBean() throws Exception {        ProviderManager manager = new ProviderManager(kaptchaAuthenticationProvider());        return manager;    }    @Override    protected 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 {    @Override    public 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 {    @Override    protected void configure(AuthenticationManagerBuilder auth)            throws Exception {        auth.inMemoryAuthentication()                .withUser("javaboy")                .password("{noop}123")                .roles("admin");    }    @Override    @Bean    public AuthenticationManager authenticationManagerBean()            throws Exception {        return super.authenticationManagerBean();    }    @Bean    LoginFilter 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;    }    @Override    protected 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 Security添加验证码的方式有哪些"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0