java之图形验证码的实现

我们一般在做登录的时候,都会用到图像验证码,一般都是数字和字符,今天我们就来实现下。

搭建一个maven项目

导入所需的maven依赖:

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <properties>
        <java.version>1.8</java.version>
        <dcsoft-framework-utility.version>2.0-SNAPSHOT</dcsoft-framework-utility.version>
    </properties>

    <dependencies>

        <!-- redis 集成-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!--阿里json包-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.41</version>
        </dependency>
        <!--web起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--springboot起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>



        <!--spring-boot测试工具起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

然后创建启动类,把项目跑起来

@SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class ZiGaoApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZiGaoApplication.class, args);
    }


}

常量定义:

public class Consts {

    /**
     * 验证码
     */
    public static final String LOGIN_CAPTCHA = "login_captcha:";
    /**
     * 一秒钟
     */
    public static final long ONE_SECOND = 1;
    /**
     * 一分钟
     */
    public static final long ONE_MINUTE = ONE_SECOND * 60;
    /**
     *一小时
     */
    public static final long ONE_HOUR = ONE_MINUTE * 60;

    /**
     * 一天
     */
    public static final long ONE_DAY = ONE_HOUR * 24;
}

图形验证码类:

public class CaptchaHelper {
    private String randString = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
    private int width = 95;
    private int height = 25;

    public CaptchaHelper() {
    }

    private Font getFont() {
        return new Font("Fixedsys", 1, 18);
    }

    private Color getRandColor(int fc, int bc) {
        if (fc > 255) {
            fc = 255;
        }

        if (bc > 255) {
            bc = 255;
        }

        Random random = new Random();
        int r = fc + random.nextInt(bc - fc - 16);
        int g = fc + random.nextInt(bc - fc - 14);
        int b = fc + random.nextInt(bc - fc - 18);
        return new Color(r, g, b);
    }

    private String drawString(Graphics g, String randomString, int i) {
        g.setFont(this.getFont());
        Random random = new Random();
        g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121)));
        String rand = this.getRandomString(random.nextInt(this.randString.length()));
        randomString = randomString + rand;
        g.translate(random.nextInt(3), random.nextInt(3));
        g.drawString(rand, 13 * i, 16);
        return randomString;
    }

    private void drawLine(Graphics g) {
        Random random = new Random();
        int x = random.nextInt(this.width);
        int y = random.nextInt(this.height);
        int xl = random.nextInt(13);
        int yl = random.nextInt(15);
        g.drawLine(x, y, x + xl, y + yl);
    }

    private String getRandomString(int num) {
        return String.valueOf(this.randString.charAt(num));
    }

    public Map<String, String> getCaptchaImg(int length) throws IOException {
        if (length < 4) {
            length = 4;
        }

        int width = 85 + 5 * (length - 4);
        int height = 25;
        int lineSize = 40 + 2 * (length - 4);
        int stringNum = length;
        BufferedImage image = new BufferedImage(width, height, 4);
        Graphics g = image.getGraphics();
        g.fillRect(0, 0, width, height);
        g.setFont(new Font("Times New Roman", 0, 18));
        g.setColor(this.getRandColor(110, 133));

        for(int i = 0; i <= lineSize; ++i) {
            this.drawLine(g);
        }

        String randomString = "";

        for(int i = 1; i <= stringNum; ++i) {
            randomString = this.drawString(g, randomString, i);
        }

        g.dispose();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(image, "jpeg", out);
        String base64bytes = Base64.getEncoder().encodeToString(out.toByteArray());
        String src = "data:image/jpeg;base64," + base64bytes;
        Map<String, String> mapResult = new LinkedHashMap();
        mapResult.put("captcha", randomString);
        mapResult.put("img", src);
        return mapResult;
    }
}

redis缓存操作类:

@Component
public class RedisRepository {
    String preFixKey;
    String mode;
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private RedisTemplate<String, String> templateForDbChange;
    private boolean dbChanged = false;
    private int changedDbNum = 0;
    private static final SerializeConfig _config;
    private static final SerializerFeature[] _features;

    public RedisRepository() {
    }

    public void setPreFixKey(String preFixKey) {
        this.preFixKey = preFixKey;
    }

    public String getMode() {
        return this.mode;
    }

    public void setMode(String mode) {
        this.mode = mode;
    }

    public String getPreFixKey() {
        return this.preFixKey;
    }

    public int getChangedDbNum() {
        return this.changedDbNum;
    }

    public void setChangedDbNum(int changedDbNum) {
        this.changedDbNum = changedDbNum;
    }

    public RedisTemplate<String, String> getTemplateForDbChange() {
        return this.templateForDbChange;
    }

    public boolean isDbChanged() {
        return this.dbChanged;
    }

    public RedisTemplate<String, String> getRedisTemplate() {
        return this.redisTemplate;
    }

    public void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void init(int dbNum) {
        if (dbNum >= 0 && dbNum <= 15) {
            this.templateForDbChange = new RedisTemplate();
            BeanUtils.copyProperties(this.redisTemplate, this.templateForDbChange);
            LettuceConnectionFactory jedisConnectionFactory = (LettuceConnectionFactory)this.redisTemplate.getConnectionFactory();
            int changeNum = jedisConnectionFactory.getDatabase();
            LettuceConnectionFactory tempCon2 = null;
            if (this.mode.equalsIgnoreCase("cluster")) {
                tempCon2 = new LettuceConnectionFactory(jedisConnectionFactory.getClusterConfiguration());
            } else if (this.mode.equalsIgnoreCase("sentinel")) {
                tempCon2 = new LettuceConnectionFactory(jedisConnectionFactory.getSentinelConfiguration());
            } else {
                tempCon2 = new LettuceConnectionFactory(jedisConnectionFactory.getStandaloneConfiguration());
            }

            tempCon2.setDatabase(dbNum);
            tempCon2.afterPropertiesSet();
            tempCon2.resetConnection();
            this.templateForDbChange.setConnectionFactory(tempCon2);
            this.templateForDbChange.afterPropertiesSet();
            this.dbChanged = true;
            this.changedDbNum = dbNum;
            System.out.println("将redis从database-" + changeNum + "切换到database-" + dbNum);
        }
    }

    private String getRedisKey(String key) {
        return this.preFixKey + key;
    }

    public boolean addItem(String key, String value, long seconds) {
        try {
            if (seconds > 0L) {
                if (this.dbChanged) {
                    this.templateForDbChange.opsForValue().set(this.getRedisKey(key), value, seconds, TimeUnit.SECONDS);
                } else {
                    this.redisTemplate.opsForValue().set(this.getRedisKey(key), value, seconds, TimeUnit.SECONDS);
                }
            } else {
                this.addForever(this.getRedisKey(key), value);
            }

            return true;
        } catch (Exception var6) {
            var6.printStackTrace();
            return false;
        }
    }

    public boolean addItem(String key, Object object, long seconds) {
        return object.getClass().equals("".getClass()) ? this.addItem(key, (String)object, seconds) : this.addItem(key, this.object2Json(object), seconds);
    }

    public boolean addForever(String key, String item) {
        try {
            if (this.dbChanged) {
                this.templateForDbChange.opsForValue().set(this.getRedisKey(key), item);
            } else {
                this.redisTemplate.opsForValue().set(this.getRedisKey(key), item);
            }

            return true;
        } catch (Exception var4) {
            var4.printStackTrace();
            return false;
        }
    }

    public boolean addForever(String key, Object object) {
        return object.getClass().equals("".getClass()) ? this.addForever(key, (String)object) : this.addForever(key, this.object2Json(object));
    }

    public boolean updateItem(String key, String value, long seconds) {
        return this.addItem(key, value, seconds);
    }

    public boolean updateItem(String key, Object object, long seconds) {
        return object.getClass().equals("".getClass()) ? this.updateItem(key, object, seconds) : this.updateItem(key, this.object2Json(object), seconds);
    }

    public boolean updateExpireTime(String key, long seconds) throws Exception {
        if (seconds < 0L) {
            throw new Exception("有效期不能小于0 !");
        } else {
            try {
                if (this.dbChanged) {
                    this.templateForDbChange.expire(this.getRedisKey(key), seconds, TimeUnit.SECONDS);
                } else {
                    this.redisTemplate.expire(this.getRedisKey(key), seconds, TimeUnit.SECONDS);
                }

                return true;
            } catch (Exception var5) {
                var5.printStackTrace();
                return false;
            }
        }
    }

    public void removeByKey(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                if (this.dbChanged) {
                    this.templateForDbChange.delete(this.getRedisKey(key[0]));
                } else {
                    this.redisTemplate.delete(this.getRedisKey(key[0]));
                }
            } else {
                List<String> listKeys = CollectionUtils.arrayToList(key);
                List<String> listNewKeys = new ArrayList();
                listKeys.forEach((k) -> {
                    listNewKeys.add(this.getRedisKey(k));
                });
                if (this.dbChanged) {
                    this.templateForDbChange.delete(listNewKeys);
                } else {
                    this.redisTemplate.delete(listNewKeys);
                }
            }
        }

    }

    public Long removeByRegex(String pattern) {
        Set keys;
        if (this.dbChanged) {
            keys = this.templateForDbChange.keys(this.getRedisKey(pattern));
            return this.templateForDbChange.delete(keys);
        } else {
            keys = this.redisTemplate.keys(this.getRedisKey(pattern));
            return this.redisTemplate.delete(keys);
        }
    }

    public boolean isExists(String key) {
        return this.dbChanged ? this.templateForDbChange.hasKey(this.getRedisKey(key)) : this.redisTemplate.hasKey(this.getRedisKey(key));
    }

    public String getItem(String key) {
        if (null == key) {
            return null;
        } else {
            String obj = null;
            if (this.dbChanged) {
                obj = (String)this.templateForDbChange.opsForValue().get(this.getRedisKey(key));
            } else {
                String tmp = (String)this.redisTemplate.opsForValue().get(this.getRedisKey(key));
                obj = tmp;
            }

            return obj;
        }
    }

    public Long increment(String key) {
        if (null == key) {
            return 0L;
        } else {
            Long obj = null;
            if (this.dbChanged) {
                obj = this.templateForDbChange.opsForValue().increment(this.getRedisKey(key));
            } else {
                obj = this.redisTemplate.opsForValue().increment(this.getRedisKey(key));
            }

            return obj;
        }
    }

    public Long increment(String key, long delta) {
        if (null == key) {
            return 0L;
        } else {
            Long obj = null;
            if (this.dbChanged) {
                obj = this.templateForDbChange.opsForValue().increment(this.getRedisKey(key), delta);
            } else {
                obj = this.redisTemplate.opsForValue().increment(this.getRedisKey(key), delta);
            }

            return obj;
        }
    }

    public Long leftPush(String key, Object obj) {
        long l = -1L;
        if (this.dbChanged) {
            l = this.templateForDbChange.opsForList().leftPush(key, this.object2Json(obj));
        } else {
            l = this.redisTemplate.opsForList().leftPush(key, this.object2Json(obj));
        }

        return l;
    }

    public String rightPop(String key) {
        String str = null;
        if (this.dbChanged) {
            str = (String)this.templateForDbChange.opsForList().rightPop(key);
        } else {
            str = (String)this.redisTemplate.opsForList().rightPop(key);
        }

        return str;
    }

    public void trim(String key, long start, long end) {
        if (this.dbChanged) {
            this.templateForDbChange.opsForList().trim(key, start, end);
        } else {
            this.redisTemplate.opsForList().trim(key, start, end);
        }

    }

    public long size(String key) {
        return this.dbChanged ? this.templateForDbChange.opsForList().size(key) : this.redisTemplate.opsForList().size(key);
    }

    private String object2Json(Object obj) {
        String json = JSON.toJSONString(obj, _config, _features);
        return json;
    }

    static {
        _features = new SerializerFeature[]{SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteNullBooleanAsFalse, SerializerFeature.WriteDateUseDateFormat};
        _config = new SerializeConfig();
    }
}

数据格式返回类:

public class ResponseMessage implements Serializable {
    int status;
    Object message;
    String errmsg;

    public int getStatus() {
        return this.status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public Object getMessage() {
        return this.message;
    }

    public void setMessage(Object message) {
        this.message = message;
    }

    public String getErrmsg() {
        return this.errmsg;
    }

    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }

    public ResponseMessage() {
    }

    public ResponseMessage(int status) {
        this.status = status;
    }

    public ResponseMessage(Object data) {
        this.status = 0;
        this.message = data;
    }

    public ResponseMessage(int status, Object data) {
        this.status = status;
        this.message = data;
    }

    public ResponseMessage(int status, Object data, String err) {
        this.status = status;
        this.message = data;
        this.errmsg = err;
    }

    public ResponseMessage(int status, String err) {
        this.status = status;
        this.errmsg = err;
    }
}

Controller层公共类:

public class BaseController {
    //日志
    public Logger logger = LoggerFactory.getLogger(this.getClass());


}

Controller层类

@RestController
@RequestMapping("/verify")
public class VerifyCodeController extends BaseController{

    //redis 缓存操作
    @Autowired
    RedisRepository redisRepository;


    /**
     * 获取验证码
     * @return
     */
    @GetMapping("/code")
    public ResponseMessage getGeneratCaptcha() {
        ResponseMessage responseMessage = new ResponseMessage(0);
        try {
            CaptchaHelper captchaHelper = new CaptchaHelper();
            Map<String, String> captchaMap = new LinkedHashMap<>();
            // 生成4位随机验证码
            captchaMap = captchaHelper.getCaptchaImg(4);
            // 封装后返回
            String captchaKey = UtilsCodes.genernateGuid();
            Map<String, Object> mapResult = new LinkedHashMap<>();
            mapResult.put("captchaKey", captchaKey);
            mapResult.put("img", captchaMap.get("img"));
            responseMessage.setMessage(mapResult);
            // redis缓存验证码1分钟
            Map<String, Object> mapCache = new LinkedHashMap<>();
            mapCache.put(captchaKey, captchaMap.get("captcha"));
            redisRepository.addItem(Consts.LOGIN_CAPTCHA + captchaKey, mapCache, Consts.ONE_MINUTE);
        } catch (Exception ex) {
            logger.error("生成验证码异常", ex);
            responseMessage.setStatus(-1);
            responseMessage.setMessage("生成验证码异常" + ex.getMessage());
        }
        return responseMessage;
    }

}

application配置文件:

server:
  port: 8888
  servlet:
    # 上下文路径
    context-path: /api
  tomcat:
    uri-encoding: UTF-8

# redis 配置
ccvb:
  framework:
    redis:
      # 前缀
      prefix: 'zigao:'
      #  模式,默认单例
      mode: single

 

我们来用post测试下:

复制验证码到浏览器进行测试:

验证码出来了。

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值