Spring Security实现添加图片验证功能

标题:

Spring Security实现添加图片验证功能

正文:
Spring Security是一个基于Spring框架的强大的安全框架,提供了身份验证和授权功能。其中,图片验证功能可以帮助我们增强安全性,防止恶意攻击和非法登录。以下是实现添加图片验证功能的完整攻略。

第一步:添加依赖

在项目的pom.xml文件中添加以下依赖:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
   <groupId>com.github.penggle</groupId>
   <artifactId>kaptcha</artifactId>
   <version>2.3.2</version>
</dependency>

其中,kaptcha库是用于生成验证码图片的库。

第二步:添加配置

在Spring Security配置类中添加以下配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private MyUserDetailsService userDetailsService;

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Bean
  public KaptchaServlet kaptchaServlet() {
    return new KaptchaServlet();
  }

  @Override
  public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/resources/**");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
        .antMatchers("/login", "/kaptcha.jpg").permitAll() // /kaptcha.jpg用于访问验证码图片
        .anyRequest().authenticated()
        .and()
      .formLogin()
        .loginPage("/login")
        .defaultSuccessUrl("/home")
        .permitAll()
        .and()
      .logout()
        .permitAll();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
  }

}

其中,configure()方法用于配置Spring Security的策略,permitAll()表示此url不需要认证,defaultSuccessUrl()用于设置登录成功后的默认url。

第三步:添加验证码图片生成器

在项目中添加KaptchaServlet类,用于生成验证码图片,代码如下:

public class KaptchaServlet extends HttpServlet {

  private static final long serialVersionUID = 1L;

  private static final String CAPTCHA_PRODUCER_FONT_SIZE = "kaptcha.textproducer.font.size";
  private static final String CAPTCHA_PRODUCER_FONT_COLOR = "kaptcha.textproducer.font.color";
  private static final String CAPTCHA_PRODUCER_CHAR_SPACE = "kaptcha.textproducer.char.space";
  private static final String CAPTCHA_PRODUCER_CHAR_LENGTH = "kaptcha.textproducer.char.length";
  private static final String CAPTCHA_IMAGE_WIDTH = "kaptcha.image.width";
  private static final String CAPTCHA_IMAGE_HEIGHT = "kaptcha.image.height";

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setHeader("Cache-Control", "no-store, no-cache");
    resp.setContentType("image/jpeg");

    Config config = new Config(new Properties());
    // 设置验证码图片的大小
    config.setProperty(CAPTCHA_IMAGE_WIDTH, "150");
    config.setProperty(CAPTCHA_IMAGE_HEIGHT, "50");
    // 设置字体大小
    config.setProperty(CAPTCHA_PRODUCER_FONT_SIZE, "30");
    // 设置字体颜色
    config.setProperty(CAPTCHA_PRODUCER_FONT_COLOR, "BLACK");
    // 设置字符间距
    config.setProperty(CAPTCHA_PRODUCER_CHAR_SPACE, "3");
    // 设置字符长度
    config.setProperty(CAPTCHA_PRODUCER_CHAR_LENGTH, "6");

    Producer producer = new DefaultKaptcha();
    ((DefaultKaptcha)producer).setConfig(config);

    String capText = producer.createText();
    req.getSession().setAttribute("captcha", capText);

    BufferedImage bi = producer.createImage(capText);
    ServletOutputStream out = resp.getOutputStream();
    ImageIO.write(bi, "jpg", out);
    out.flush();
    out.close();
  }

}

其中,通过设置Config对象的属性来设置验证码图片的大小、字体大小、字体颜色、字符间距和字符长度。

最后,通过doGet()方法生成验证码图片,并将生成的验证码设置到session中。

第四步:添加前端页面

在登录页面添加验证码输入框和验证码图片显示框,代码如下:

<body>
  <div class="container" id="login-block">
    <h2>登录页</h2>
    <form id="login-form" name="login-form" action="/login" method="post">
      <div class="form-group">
        <label for="username">用户名:</label> 
        <input type="text" class="form-control" id="username" name="username">
      </div>
      <div class="form-group">
        <label for="password">密码:</label>
        <input type="password" class="form-control" id="password" name="password">
      </div>
      <div class="form-group">
        <label for="captcha">验证码:</label> 
        <input type="text" class="form-control" id="captcha" name="captcha" style="width:100px;">
        <img src="/kaptcha.jpg" onclick="this.src='/kaptcha.jpg?'+Math.random()" alt="验证码" style="cursor: pointer;">
      </div>
      <button type="submit" class="btn btn-default">登录</button>
    </form>
  </div>
</body>

其中,通过输入框和img标签分别显示验证码输入框和验证码图片,通过onclick属性实现验证码图片的点击重新刷新。

第五步:添加自定义验证逻辑

在自定义的UserDetailsService实现类中添加验证码验证逻辑,代码如下:

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

  private static final Logger logger = LoggerFactory.getLogger(MyUserDetailsService.class);

  @Autowired
  private UserService userService;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userService.getUserByUsername(username);
    if (user == null) {
      throw new UsernameNotFoundException("用户名不存在");
    }

    String password = passwordEncoder().encode(user.getPassword());
    List<GrantedAuthority> authorities = new ArrayList<>();
    authorities.add(new SimpleGrantedAuthority(user.getRole()));

    return new org.springframework.security.core.userdetails.User(username, password, authorities) {
      private static final long serialVersionUID = 1L;

      @Override
      public boolean isEnabled() {
        return true;
      }
      @Override
      public boolean isAccountNonExpired() {
        return true;
      }
      @Override
      public boolean isAccountNonLocked() {
        return true;
      }
      @Override
      public boolean isCredentialsNonExpired() {
        return true;
      }
    };
  }

  @Autowired
  private HttpServletRequest request;

  @Override
  public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) throws UsernameNotFoundException {
    String captcha = (String) request.getSession().getAttribute("captcha");
    String inputCaptcha = (String) token.getCredentials();
    if (!captcha.equalsIgnoreCase(inputCaptcha)) {
      throw new BadCredentialsException("验证码不正确");
    }
    return loadUserByUsername((String) token.getPrincipal());
  }

  private PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

}

其中,通过loadUserDetails()方法实现验证逻辑,检查验证码是否正确。

以上就是Spring Security实现添加图片验证功能的完整攻略,通过添加依赖、配置、验证码图片生成器、前端页面和自定义验证逻辑实现了图片验证功能的增强安全性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security实现添加图片验证功能 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • Form表单上传文件(type=”file”)的使用

    下面是关于“Form表单上传文件(type=”file”)的使用”的完整攻略。 什么是表单上传文件 表单上传文件是指通过HTML表单允许用户上传文件。它使用表单元素的type属性设置为“file”,可以让用户选择一个或多个文件。 表单上传文件的实现步骤 要使用表单上传文件,需要以下步骤: 在HTML页面中创建一个表单元素,并将其类型设置为“post”,同时指…

    Java 2023年6月15日
    00
  • 详解Spring Boot实战之Restful API的构建

    详解SpringBoot实战之RestfulAPI的构建攻略 介绍 本文将详细介绍如何使用Spring Boot构建一个带有Restful API的Web应用,并以具体示例来说明其中的细节和注意事项。 环境准备 在开始前,请确保已经安装好以下环境:- JDK 8或以上版本- Maven 3.x或以上版本- IDEA或其他Java IDE 创建新项目 首先,我…

    Java 2023年5月15日
    00
  • Spring security基于数据库中账户密码认证

    Spring Security是Spring框架中提供的一个安全权限框架。它将认证(Authentication)和授权(Authorization)抽象为一个独立的模块,可以快速地将安全性集成到应用程序中。Spring Security可以基于多种认证方式,包括基于数据库中账户密码的认证。 基于数据库中账户密码认证的Spring Security攻略如下:…

    Java 2023年5月20日
    00
  • 从源码角度深入解析Callable接口

    摘要:从源码角度深入解析Callable接口,希望大家踏下心来,打开你的IDE,跟着文章看源码,相信你一定收获不小。 本文分享自华为云社区《一个Callable接口能有多少知识点?》,作者: 冰 河。 并发编程一直是程序员们比较头疼的,如何编写正确的并发程序相比其他程序来说,是一件比较困难的事情,并发编程中出现的 Bug 往往也是特别诡异的。 之所以说并发编…

    Java 2023年4月18日
    00
  • Java 进行时间处理的步骤

    Java 进行时间处理的步骤可以分为以下几个方面: 获取当前时间 Java 可以使用 java.util.Date 或 java.time.LocalDateTime 类获取当前的系统时间。其中,java.util.Date 是一个在 Java 8 之前使用的类,而在 Java 8 及以后,建议使用 java.time.LocalDateTime 类。 示例…

    Java 2023年5月20日
    00
  • Java中的继承详情

    下面是关于Java中继承的详细讲解和示例说明: 什么是继承? 在Java中,继承是一种面向对象编程的重要特性,它允许一个类(称为子类)继承另一个类(称为父类)的属性和方法。继承机制允许子类重写父类的方法或添加自己的属性和方法。 如何实现继承? 在Java中,使用关键字extends实现继承,具体语法为: class SubClass extends Supe…

    Java 2023年5月26日
    00
  • Java日期时间类及计算详解

    Java日期时间类及计算详解 Java中提供了多个日期时间类,用于操作和计算日期和时间。本文将详细介绍Java日期时间类及计算的相关知识。 Date类 Date类是Java中最基本的日期时间类。它表示时间戳,即自1970年1月1日00:00:00至当前日期时间所经过的毫秒数。 获取当前日期时间 要获取当前日期时间,可以使用Date类的无参构造函数和toStr…

    Java 2023年5月20日
    00
  • Mybatis中注入执行sql查询、更新、新增及建表语句案例代码

    让我来为你讲解Mybatis中注入执行SQL查询、更新、新增及建表语句的完整攻略。 什么是Mybatis? Mybatis是一个Java持久化框架,它可以帮助我们将Java对象与关系型数据库之间建立映射关系,同时提供了大量的查询、更新、新增和删除数据的API。 Mybatis支持多种ORM(对象关系映射)方式,其中比较常用的是注解和XML配置文件。本文将主要…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部