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

时间:2022-10-31 10:11:03

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

生成图形验证码

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

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

根据随机数生成图片

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
 * 生成图形验证码
 * @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中 && 将生成的图片写到接口的响应中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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之前进行校验。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@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之前:

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

代码下载

spring-security

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

原文链接:https://blog.csdn.net/u013435893/article/details/79617872