经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
Spring Security添加验证码的两种方式小结
来源:jb51  时间:2021/10/8 13:06:10  对本文有异议

一、自定义认证逻辑

生成验证码工具

  1. <dependency>
  2. <groupId>com.github.penggle</groupId>
  3. <artifactId>kaptcha</artifactId>
  4. <version>2.3.2</version>
  5. </dependency>

添加Kaptcha配置

  1. @Configuration
  2. public class KaptchaConfig {
  3. @Bean
  4. Producer kaptcha() {
  5. Properties properties = new Properties();
  6. properties.setProperty("kaptcha.image.width", "150");
  7. properties.setProperty("kaptcha.image.height", "50");
  8. properties.setProperty("kaptcha.textproducer.char.string", "0123456789");
  9. properties.setProperty("kaptcha.textproducer.char.length", "4");
  10. Config config = new Config(properties);
  11. DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
  12. defaultKaptcha.setConfig(config);
  13. return defaultKaptcha;
  14. }
  15. }

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

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

  1. @RestController
  2. public class LoginController {
  3. @Autowired
  4. Producer producer;
  5. @GetMapping("/vc.jpg")
  6. public void getVerifyCode(HttpServletResponse resp, HttpSession session) throws IOException {
  7. resp.setContentType("image/jpeg");
  8. String text = producer.createText();
  9. session.setAttribute("kaptcha", text);
  10. BufferedImage image = producer.createImage(text);
  11. try(ServletOutputStream out = resp.getOutputStream()) {
  12. ImageIO.write(image, "jpg", out);
  13. }
  14. }
  15. @RequestMapping("/index")
  16. public String index() {
  17. return "login success";
  18. }
  19. @RequestMapping("/hello")
  20. public String hello() {
  21. return "hello spring security";
  22. }
  23. }

form表单

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录</title>
  6. <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="external nofollow" rel="stylesheet" id="bootstrap-css">
  7. <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
  8. <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  9. </head>
  10. <style>
  11. #login .container #login-row #login-column #login-box {
  12. border: 1px solid #9C9C9C;
  13. background-color: #EAEAEA;
  14. }
  15. </style>
  16. <body>
  17. <div id="login">
  18. <div class="container">
  19. <div id="login-row" class="row justify-content-center align-items-center">
  20. <div id="login-column" class="col-md-6">
  21. <div id="login-box" class="col-md-12">
  22. <form id="login-form" class="form" action="/doLogin" method="post">
  23. <h3 class="text-center text-info">登录</h3>
  24. <div th:text="${SPRING_SECURITY_LAST_EXCEPTION}"></div>
  25. <div class="form-group">
  26. <label for="username" class="text-info">用户名:</label><br>
  27. <input type="text" name="uname" id="username" class="form-control">
  28. </div>
  29. <div class="form-group">
  30. <label for="password" class="text-info">密码:</label><br>
  31. <input type="text" name="passwd" id="password" class="form-control">
  32. </div>
  33. <div class="form-group">
  34. <label for="kaptcha" class="text-info">验证码:</label><br>
  35. <input type="text" name="kaptcha" id="kaptcha" class="form-control">
  36. <img src="/vc.jpg" alt="">
  37. </div>
  38. <div class="form-group">
  39. <input type="submit" name="submit" class="btn btn-info btn-md" value="登录">
  40. </div>
  41. </form>
  42. </div>
  43. </div>
  44. </div>
  45. </div>
  46. </div>
  47. </body>

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

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

  1. public class KaptchaAuthenticationProvider extends DaoAuthenticationProvider {
  2.  
  3. @Override
  4. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  5. HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  6. String kaptcha = req.getParameter("kaptcha");
  7. String sessionKaptcha = (String) req.getSession().getAttribute("kaptcha");
  8. if (kaptcha != null && sessionKaptcha != null && kaptcha.equalsIgnoreCase(sessionKaptcha)) {
  9. return super.authenticate(authentication);
  10. }
  11. throw new AuthenticationServiceException("验证码输入错误");
  12. }
  13. }

配置AuthenticationManager:

  1. @Configuration
  2. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  3.  
  4. @Bean
  5. AuthenticationProvider kaptchaAuthenticationProvider() {
  6. InMemoryUserDetailsManager users = new InMemoryUserDetailsManager(User.builder()
  7. .username("xiepanapn").password("{noop}123").roles("admin").build());
  8. KaptchaAuthenticationProvider provider = new KaptchaAuthenticationProvider();
  9. provider.setUserDetailsService(users);
  10. return provider;
  11. }
  12.  
  13. @Override
  14. @Bean
  15. public AuthenticationManager authenticationManagerBean() throws Exception {
  16. ProviderManager manager = new ProviderManager(kaptchaAuthenticationProvider());
  17. return manager;
  18. }
  19.  
  20. @Override
  21. protected void configure(HttpSecurity http) throws Exception {
  22. http.authorizeRequests()
  23. .antMatchers("/vc.jpg").permitAll()
  24. .anyRequest().authenticated()
  25. .and()
  26. .formLogin()
  27. .loginPage("/mylogin.html")
  28. .loginProcessingUrl("/doLogin")
  29. .defaultSuccessUrl("/index.html")
  30. .failureForwardUrl("/mylogin.html")
  31. .usernameParameter("uname")
  32. .passwordParameter("passwd")
  33. .permitAll()
  34. .and()
  35. .csrf().disable();
  36. }
  37. }
  1. 配置UserDetailsService提供的数据源
  2. 提供AuthenticationProvider实例并配置UserDetailsService
  3. 重写authenticationManagerBean方法提供一个自己的ProviderManager并自定义AuthenticationManager实例。

二、自定义过滤器

LoginFilter继承UsernamePasswordAuthenticationFilter 重写attemptAuthentication方法:

  1. public class LoginFilter extends UsernamePasswordAuthenticationFilter {
  2.  
  3. @Override
  4. public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
  5. if (!request.getMethod().equals("POST")) {
  6. throw new AuthenticationServiceException(
  7. "Authentication method not supported: " + request.getMethod());
  8. }
  9. String kaptcha = request.getParameter("kaptcha");
  10. String sessionKaptcha = (String) request.getSession().getAttribute("kaptcha");
  11. if (!StringUtils.isEmpty(kaptcha) && !StringUtils.isEmpty(sessionKaptcha) && kaptcha.equalsIgnoreCase(sessionKaptcha)) {
  12. return super.attemptAuthentication(request, response);
  13. }
  14. throw new AuthenticationServiceException("验证码输入错误");
  15. }
  16. }

在SecurityConfig中配置LoginFilter

  1. @Configuration
  2. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  3. @Override
  4. protected void configure(AuthenticationManagerBuilder auth)
  5. throws Exception {
  6. auth.inMemoryAuthentication()
  7. .withUser("javaboy")
  8. .password("{noop}123")
  9. .roles("admin");
  10. }
  11.  
  12. @Override
  13. @Bean
  14. public AuthenticationManager authenticationManagerBean()
  15. throws Exception {
  16. return super.authenticationManagerBean();
  17. }
  18.  
  19. @Bean
  20. LoginFilter loginFilter() throws Exception {
  21. LoginFilter loginFilter = new LoginFilter();
  22. loginFilter.setFilterProcessesUrl("/doLogin");
  23. loginFilter.setAuthenticationManager(authenticationManagerBean());
  24. loginFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/hello"));
  25. loginFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/mylogin.html"));
  26. return loginFilter;
  27. }
  28.  
  29. @Override
  30. protected void configure(HttpSecurity http) throws Exception {
  31. http.authorizeRequests()
  32. .antMatchers("/vc.jpg").permitAll()
  33. .anyRequest().authenticated()
  34. .and()
  35. .formLogin()
  36. .loginPage("/mylogin.html")
  37. .permitAll()
  38. .and()
  39. .csrf().disable();
  40. http.addFilterAt(loginFilter(),
  41. UsernamePasswordAuthenticationFilter.class);
  42. }
  43. }

显然第二种比较简单

总结

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号