欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot结合SpringSecurity实现图形验证码功能

程序员文章站 2023-12-16 09:15:28
本文介绍了springboot结合springsecurity实现图形验证码功能,分享给大家,具体如下: 生成图形验证码 根据随机数生成图片 将随机数存到...

本文介绍了springboot结合springsecurity实现图形验证码功能,分享给大家,具体如下:

生成图形验证码

  1. 根据随机数生成图片
  2. 将随机数存到session中
  3. 将生成的图片写到接口的响应中

生成图形验证码的过程比较简单,和springsecurity也没有什么关系。所以就直接贴出代码了

根据随机数生成图片

/**
 * 生成图形验证码
 * @param request
 * @return
 */
private imagecode generate(servletwebrequest request) {
 int width = 64;
 int height = 32;
 bufferedimage image = new bufferedimage(width, height, bufferedimage.type_int_rgb);

 graphics g = image.getgraphics();

 random random = new random();

 g.setcolor(getrandcolor(200, 250));
 g.fillrect(0, 0, width, height);
 g.setfont(new font("times new roman", font.italic, 20));
 g.setcolor(getrandcolor(160, 200));
 for (int i = 0; i < 155; i++) {
  int x = random.nextint(width);
  int y = random.nextint(height);
  int xl = random.nextint(12);
  int yl = random.nextint(12);
  g.drawline(x, y, x + xl, y + yl);
 }

 string srand = "";
 for (int i = 0; i < 4; i++) {
  string rand = string.valueof(random.nextint(10));
  srand += rand;
  g.setcolor(new color(20 + random.nextint(110), 20 + random.nextint(110), 20 + random.nextint(110)));
  g.drawstring(rand, 13 * i + 6, 16);
 }

 g.dispose();

 return new imagecode(image, srand, 60);

}

/**
 * 生成随机背景条纹
 *
 * @param fc
 * @param bc
 * @return
 */
private color getrandcolor(int fc, int bc) {
 random random = new random();
 if (fc > 255) {
  fc = 255;
 }
 if (bc > 255) {
  bc = 255;
 }
 int r = fc + random.nextint(bc - fc);
 int g = fc + random.nextint(bc - fc);
 int b = fc + random.nextint(bc - fc);
 return new color(r, g, b);
}

将随机数存到session中 && 将生成的图片写到接口的响应中

@restcontroller
public class validatecodecontroller {

 public static final string session_key = "session_key_image_code";

 private sessionstrategy sessionstrategy = new httpsessionsessionstrategy();

 @getmapping("/code/image")
 public void createcode(httpservletrequest request, httpservletresponse response) throws ioexception {
  imagecode imagecode = generate(new servletwebrequest(request));
  sessionstrategy.setattribute(new servletwebrequest(request), session_key, imagecode);
  imageio.write(imagecode.getimage(), "jpeg", response.getoutputstream());
 }
}

在认证流程中加入图形验证码

springsecurity认证流程详解中,我们有讲到,springsecurity是通过过滤器链来进行校验的,我们想要验证图形验证码,所以可以在认证流程之前,也就是usernamepasswordauthenticationfilter之前进行校验。

自定义图形验证码的过滤器

@component
public class validatecodefilter extends onceperrequestfilter {

 private sessionstrategy sessionstrategy = new httpsessionsessionstrategy();

 private authenticationfailurehandler authenticationfailurehandler;

 @override
 protected void dofilterinternal(httpservletrequest httpservletrequest, httpservletresponse httpservletresponse, filterchain filterchain) throws servletexception, ioexception {
  if(stringutils.equals("/user/login", httpservletrequest.getrequesturi())
    && stringutils.equalsignorecase(httpservletrequest.getmethod(), "post")) {

   try {
    // 1. 进行验证码的校验
    validate(new servletwebrequest(httpservletrequest));
   } catch (validatecodeexception e) {
    // 2. 如果校验不通过,调用springsecurity的校验失败处理器
    authenticationfailurehandler.onauthenticationfailure(httpservletrequest, httpservletresponse, e);
    return ;
   }
  }
  // 3. 校验通过,就放行
  filterchain.dofilter(httpservletrequest, httpservletresponse);
 }
} 

这里验证码校验的过程比较简单,主要就是判断传过来的参数和session中保存的是否一致,以及session中的验证码是否过期了。

有了自己的验证码过滤器之后,我们还需要将它配置在usernamepasswordauthenticationfilter之前:

@override
protected void configure(httpsecurity http) throws exception {
 validatecodefilter validatecodefilter = new validatecodefilter();
 validatecodefilter.setauthenticationfailurehandler(myauthenticationfailurehandler);
 // 将我们自定义的过滤器,配置到usernamepasswordauthenticationfilter之前
 http.addfilterbefore(validatecodefilter, usernamepasswordauthenticationfilter.class)
   .formlogin()     // 定义当需要用户登录时候,转到的登录页面。
   // 后面的配置省略
}    

代码下载

spring-security

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: