shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package com.walker.support.kaptcha;
 
import com.walker.infrastructure.utils.StringUtils;
import com.walker.web.CaptchaProvider;
import com.walker.web.CaptchaResult;
import com.walker.web.CaptchaType;
 
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Random;
 
/**
 * 只有文字的验证码,数字或者字母。
 * @author 时克英
 * @date 2023-05-12
 */
public class WordCaptchaProvider implements CaptchaProvider<CaptchaResult> {
 
    private static final Random random = new Random();
 
    private final int width = 80;     //图片宽度
    private final int height = 34;    //图片高度
    private final int stringNum = 4;  //字符的数量
    private final int lineSize = 40;  //干扰线数量
 
    @Override
    public CaptchaResult generateCaptcha(Object param) {
        CaptchaResult captchaResult = new CaptchaResult();
        BufferedImage image = this.createImage(captchaResult);
//        captchaResult.setCode(code);
        captchaResult.setImage(image);
        return captchaResult;
    }
 
    @Override
    public boolean validateCaptcha(CaptchaResult data) {
        // 由业务子类继承并重写该方法完成校验,一般会把生成结果放入缓存,然后与给定的结果做对比。
        return false;
    }
 
    @Override
    public CaptchaType getCaptchaType() {
        return CaptchaType.InputCode;
    }
 
    private BufferedImage createImage(CaptchaResult captchaResult){
        Graphics Graphics = null;
        try {
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
            Graphics = image.getGraphics();// 获得BufferedImage对象的Graphics对象
            Graphics.fillRect(0, 0, width, height);//填充矩形
            Graphics.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));//设置字体
            Graphics.setColor(getRandColor(110, 133));//设置颜色
            //绘制干扰线
            for(int i = 0; i <= lineSize; i++) {
                drawLine(Graphics);
            }
            //绘制字符
            String randomString = "";
            for(int i = 1; i <= stringNum; i++) {
                randomString = drawString(Graphics, randomString, i);
                captchaResult.setCode(randomString);
            }
            return image;
 
        } catch (Exception ex){
            ex.printStackTrace();
            return null;
 
        } finally {
            if(Graphics != null){
                Graphics.dispose();//释放绘图资源
            }
        }
    }
 
    /**
     * 绘制字符串,返回绘制的字符串
     * @param graphics 获得BufferedImage对象的Graphics对象
     * @param randomString 随机字符串
     * @param i 坐标倍数
 
     * @since 2020-04-16
     * @return string
     */
    private String drawString(Graphics graphics, String randomString, int i) {
        Graphics2D g2d = (Graphics2D) graphics;
        g2d.setFont(getFont());   //设置字体
        g2d.setColor(new Color(random.nextFloat(), random.nextFloat(), random.nextFloat()));//设置颜色
        String randChar = getRandomChar(random.nextInt(StringUtils.STRING_RANDOM_CHAR.length()));
        randomString += randChar;   //组装
//        int rot = getRandomNum(1,10);
        int rot = Integer.parseInt(StringUtils.generateRandomNumber(1));
//        System.out.println(".......... rot = " + rot);
        g2d.translate(random.nextInt(3), random.nextInt(3));
        g2d.rotate(rot * Math.PI / 180);
        g2d.drawString(randChar, 13*i, 20);
        g2d.rotate(-rot * Math.PI / 180);
        return randomString;
    }
 
    private void drawLine(Graphics graphics) {
        //起点(x,y)  偏移量x1、y1
        int x = random.nextInt(width);
        int y = random.nextInt(height);
        int xl = random.nextInt(13);
        int yl = random.nextInt(15);
        graphics.setColor(new Color(random.nextFloat(), random.nextFloat(), random.nextFloat()));
        graphics.drawLine(x, y, x + xl, y + yl);
    }
 
    private Font getFont() {
        return new Font("Fixedsys", Font.CENTER_BASELINE, 25);  //名称、样式、磅值
    }
 
    private String getRandomChar(int index) {
        //获取指定位置index的字符,并转换成字符串表示形式
        return String.valueOf(StringUtils.STRING_RANDOM_CHAR.charAt(index));
    }
 
    private Color getRandColor(int frontColor, int backColor) {
        if(frontColor > 255)
            frontColor = 255;
        if(backColor > 255)
            backColor = 255;
 
        int red = frontColor + random.nextInt(backColor - frontColor - 16);
        int green = frontColor + random.nextInt(backColor - frontColor -14);
        int blue = frontColor + random.nextInt(backColor - frontColor -18);
        return new Color(red, green, blue);
    }
}