温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2021-10-08 13:42:13 来源:亿速云 阅读:425 作者:iii 栏目:开发技术

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

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

  • 二、自定义过滤器

一、自定义认证逻辑

生成验证码工具

<dependency>     <groupId>com.github.penggle</groupId>     <artifactId>kaptcha</artifactId>     <version>2.3.2</version> </dependency>

添加Kaptcha配置

@Configuration public 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流写出到前端。

@RestController public 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表单

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head>     <meta charset="UTF-8">     <title>登录</title>     <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="external nofollow"  rel="stylesheet" id="bootstrap-css">     <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>     <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> </head> <style>     #login .container #login-row #login-column #login-box {         border: 1px solid #9C9C9C;         background-color: #EAEAEA;     } </style> <body> <div id="login">     <div class="container">         <div id="login-row" class="row justify-content-center align-items-center">             <div id="login-column" class="col-md-6">                 <div id="login-box" class="col-md-12">                     <form id="login-form" class="form" action="/doLogin" method="post">                         <h4 class="text-center text-info">登录</h4>                         <div th:text="${SPRING_SECURITY_LAST_EXCEPTION}"></div>                         <div class="form-group">                             <label for="username" class="text-info">用户名:</label><br>                             <input type="text" name="uname" id="username" class="form-control">                         </div>                         <div class="form-group">                             <label for="password" class="text-info">密码:</label><br>                             <input type="text" name="passwd" id="password" class="form-control">                         </div>                         <div class="form-group">                             <label for="kaptcha" class="text-info">验证码:</label><br>                             <input type="text" name="kaptcha" id="kaptcha" class="form-control">                             <img src="/vc.jpg" alt="">                         </div>                         <div class="form-group">                             <input type="submit" name="submit" class="btn btn-info btn-md" value="登录">                         </div>                     </form>                 </div>             </div>         </div>     </div> </div> </body>

验证码图片地址为我们在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:

@Configuration public 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

@Configuration public 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添加验证码的方式有哪些”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI