好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SpringBoot+kaptcha实现验证码花式玩法详解

在 vhr 项目中,松哥也跟大家讲了验证码的用法,不过那个里边的验证码是我们自己写的,其实功能也还算完整,够用。不过现在各个网站的验证码玩法花样越来越多,加上最近在搞的 TienChin 项目用的验证码是一个老牌开源库 kaptcha,所以松哥决定还是花点时间,跟大家聊聊 kaptcha 的用法,毕竟这个已经有 16 年历史的玩意还在有人用,说明它的功能还是相当强大的。

1. 基本用法

kaptcha 是一个非常老牌的验证码生成工具,多老呢?可以追溯到 2006 年。

这么多年过去了,它不仅没有落寞反而还在被不少人使用,足以说明它的生命力了,值得我们来研究下。

方便起见,我们整一个 Spring Boot 工程来演示它的用法。

首先新建一个 Spring Boot 工程,然后加入 kaptcha 的依赖,如下:

?

1

2

3

4

5

< dependency >

   < groupId >com.github.penggle</ groupId >

   < artifactId >kaptcha</ artifactId >

   < version >2.3.2</ version >

</ dependency >

接下来我们只需要提供一个配置 Kaptcha 的 Bean 即可,如下:

?

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

@Configuration

public   class   KaptchaConfig {

     @Bean (name =  "captchaProducer" )

     public   DefaultKaptcha getKaptchaBean() {

         DefaultKaptcha defaultKaptcha =  new   DefaultKaptcha();

         Properties properties =  new   Properties();

         // 是否有边框 默认为true 我们可以自己设置yes,no

         properties.setProperty(KAPTCHA_BORDER,  "yes" );

         // 验证码文本字符颜色 默认为Color.BLACK

         properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR,  "black" );

         // 验证码图片宽度 默认为200

         properties.setProperty(KAPTCHA_IMAGE_WIDTH,  "160" );

         // 验证码图片高度 默认为50

         properties.setProperty(KAPTCHA_IMAGE_HEIGHT,  "60" );

         // 验证码文本字符大小 默认为40

         properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE,  "38" );

         // KAPTCHA_SESSION_KEY

         properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY,  "kaptchaCode" );

         // 验证码文本字符长度 默认为5

         properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH,  "4" );

         // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)

         properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES,  "Arial,Courier" );

         // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy

         properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL,  "com.google.code.kaptcha.impl.ShadowGimpy" );

         Config config =  new   Config(properties);

         defaultKaptcha.setConfig(config);

         return   defaultKaptcha;

     }

}

DefaultKaptcha 中配置验证码图片的各个属性值。各个属性的含义,代码中都有注释,我就不再多说了。

接下来我们在接口中返回验证码图片,如下:

?

1

2

3

4

5

6

7

8

@Autowired

DefaultKaptcha defaultKaptcha;

@GetMapping ( "/img" )

public   void   getKaptcha(HttpServletResponse resp)  throws   IOException {

     String text = defaultKaptcha.createText();

     BufferedImage image = defaultKaptcha.createImage(text);

     ImageIO.write(image,  "jpg" , resp.getOutputStream());

}

我这里是通过 IO 流的形式将图片写到前端的,当然也可以将之转为一个 Base64 字符串返回到前端,一样也是 OK 的。

等等,似乎少了什么!

我们没有把生成的验证码文本存入到 session 中去,这样一会登录的时候没法验证,有小伙伴可能会说,这还不简单?接口里边存一下不就行了?

NONONO!

大家看,当我们配置 DefaultKaptcha bean 的时候,其中有这么一行代码  properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); ,这行代码的意思就是说会自动将生成的验证码文本存入到 session 中,并且 session 的 KEY 是 kaptchaCode。但是在实际测试中,大家会发现上面的代码并不会将验证码生成的文本存入到 session 中。

原因在于 Kaptcha 工具实际上自己提供了一个生成验证码图片的 Servlet,如果我们直接使用它自己提供的验证码 Servlet,那么上面这个配置才会生效,在 Spring Boot 中,如果想要配置 Kaptcha 自己提供的 Servlet,方式如下:

?

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

@Bean

ServletRegistrationBean<HttpServlet> kaptchaServlet() {

     ServletRegistrationBean<HttpServlet> bean =  new   ServletRegistrationBean<>();

     bean.setServlet( new   KaptchaServlet());

     bean.addUrlMappings( "/img" );

     Properties properties =  new   Properties();

     // 是否有边框 默认为true 我们可以自己设置yes,no

     properties.setProperty(KAPTCHA_BORDER,  "yes" );

     // 验证码文本字符颜色 默认为Color.BLACK

     properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR,  "black" );

     // 验证码图片宽度 默认为200

     properties.setProperty(KAPTCHA_IMAGE_WIDTH,  "160" );

     // 验证码图片高度 默认为50

     properties.setProperty(KAPTCHA_IMAGE_HEIGHT,  "60" );

     // 验证码文本字符大小 默认为40

     properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE,  "38" );

     // KAPTCHA_SESSION_KEY

     properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY,  "kaptchaCode" );

     // 验证码文本字符长度 默认为5

     properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH,  "4" );

     // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)

     properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES,  "Arial,Courier" );

     // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy

     properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL,  "com.google.code.kaptcha.impl.ShadowGimpy" );

     Map<String, String> map =  new   HashMap<String,String>((Map)properties);

     bean.setInitParameters(map);

     return   bean;

}

项目启动后,直接访问  /img  就能看到验证码图片,此时验证码的文本也会自动存入到 session 中。当用户登录的时候,通过  session.getAttribute("kaptchaCode")  就可以获取到验证码的文本内容。

然而很多时候,验证码接口返回的内容都是比较丰富的,可能不仅仅是图片,还有其他信息。所以我们直接配一个 Servlet 并不能满足我们的要求,只能自己写验证码的接口,自己写的话,就要自己把验证码图片存到 session 中去,那么  properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");  配置其实就没用了,可以不用加。

2. 自定义验证码文本

当然,我们也可以自定义验证码文本,只需要提供一个验证码文本的实现类即可,如下:

?

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

public   class   KaptchaTextCreator  extends   DefaultTextCreator {

     private   static   final   String[] CNUMBERS =  "0,1,2,3,4,5,6,7,8,9,10" .split( "," );

 

     @Override

     public   String getText() {

         Integer result =  0 ;

         Random random =  new   Random();

         int   x = random.nextInt( 10 );

         int   y = random.nextInt( 10 );

         StringBuilder suChinese =  new   StringBuilder();

         int   randomoperands = ( int ) Math.round(Math.random() *  2 );

         if   (randomoperands ==  0 ) {

             result = x * y;

             suChinese.append(CNUMBERS[x]);

             suChinese.append( "*" );

             suChinese.append(CNUMBERS[y]);

         }  else   if   (randomoperands ==  1 ) {

             if   (!(x ==  0 ) && y % x ==  0 ) {

                 result = y / x;

                 suChinese.append(CNUMBERS[y]);

                 suChinese.append( "/" );

                 suChinese.append(CNUMBERS[x]);

             }  else   {

                 result = x + y;

                 suChinese.append(CNUMBERS[x]);

                 suChinese.append( "+" );

                 suChinese.append(CNUMBERS[y]);

             }

         }  else   if   (randomoperands ==  2 ) {

             if   (x >= y) {

                 result = x - y;

                 suChinese.append(CNUMBERS[x]);

                 suChinese.append( "-" );

                 suChinese.append(CNUMBERS[y]);

             }  else   {

                 result = y - x;

                 suChinese.append(CNUMBERS[y]);

                 suChinese.append( "-" );

                 suChinese.append(CNUMBERS[x]);

             }

         }  else   {

             result = x + y;

             suChinese.append(CNUMBERS[x]);

             suChinese.append( "+" );

             suChinese.append(CNUMBERS[y]);

         }

         suChinese.append( "=?@"   + result);

         return   suChinese.toString();

     }

}

这段代码并不难理解,生成的验证码文本类似于  1+1=?@2  这样的字符串。

将来以@为分界线,将@前面的字符串内容绘制到图片上,@后面的内容存到 session 中,和用户上传的内容进行比较即可。

当然,我们还需要在配置验证码的时候添加如下属性,以修改验证码文本的提供类:

?

1

properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL,  "org.javaboy.tienchin.framework.config.KaptchaTextCreator" );

配置完成后,将来在接口中直接使用这个验证码即可,用的时候注意将生成的验证码文本拆分后处理,一部分用来绘图,一部分用来存到 session 中。

完整的代码,小伙伴们可以参考 TienChin 项目

以上就是SpringBoot+kaptcha实现验证码花式玩法详解的详细内容,更多关于SpringBoot kaptcha验证码的资料请关注其它相关文章!

原文链接:https://mp.weixin.qq测试数据/s/94R51EMZJl0cg32wRNDIMg

查看更多关于SpringBoot+kaptcha实现验证码花式玩法详解的详细内容...

  阅读:14次