标题:
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技术站