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

Springboot +redis+谷歌开源Kaptcha实现图片验证码功能

程序员文章站 2022-06-09 20:11:10
背景注册-登录-修改密码⼀般需要发送验证码,但是容易被 攻击恶意调⽤什么是短信-邮箱轰炸机手机短信轰炸机是批、循环给⼿机⽆限发送各种⽹ 站的注册验 证码短信的方法。公司带来的损失短信⼀条5分钱,如果被...

背景

  • 注册-登录-修改密码⼀般需要发送验证码,但是容易被 攻击恶意调⽤
  • 什么是短信-邮箱轰炸机
    • 手机短信轰炸机是批、循环给⼿机⽆限发送各种⽹ 站的注册验 证码短信的方法。
  • 公司带来的损失
    • 短信⼀条5分钱,如果被⼤盗刷大家自己计算 邮箱通知不⽤钱,但被⼤盗刷,带宽、连接等都被占⽤,导致无法正常使⽤
  • 如何避免自己的网站成为”肉鸡“或者被刷呢
    • 增加图形验证码(开发人员)
    • 单ip请求次数限制(开发人员)
    • 限制号码发送(⼀般短信提供商会做)
    • 攻防永远是有的,只过加大了攻击者的成本,roi划不过来⾃然就放弃了

kaptcha 框架介绍

⾕歌开源的⼀个可高度配置的实⽤验证码生成⼯具

  • 验证码的字体/大小/颜⾊

  • 验证码内容的范围(数字,字⺟,中⽂汉字!)

  • 验证码图⽚的大小,边框,边框粗细,边框颜⾊

  • 验证码的⼲扰线 验证码的样式(鱼眼样式、3d、普通 模糊)

添加依赖

<!--kaptcha依赖包-->
<dependency>
 <groupid>com.baomidou</groupid>
 <artifactid>kaptcha-spring-bootstarter</artifactid>
 <version>1.0.0</version>
 </dependency>

配置类

/**
 * 图像验证码的配置文件
 * @author : look-word
 * @date : 2022-01-28 17:10
 **/
@configuration
public class captchaconfig {
    /**
     * 验证码配置
     * kaptcha配置类名
     *
     * @return
     */
    @bean
    @qualifier("captchaproducer")
    public defaultkaptcha kaptcha() {
        defaultkaptcha kaptcha = new defaultkaptcha();
        properties properties = new properties();
        //验证码个数
        properties.setproperty(constants.kaptcha_textproducer_char_length, "4");
        //字体间隔
        properties.setproperty(constants.kaptcha_textproducer_char_space,"8");
        //⼲扰线颜⾊

        //⼲扰实现类
        properties.setproperty(constants.kaptcha_noise_impl, "com.google.code.kaptcha.impl.nonoise");
        //图⽚样式
        properties.setproperty(constants.kaptcha_obscurificator_impl,
                "com.google.code.kaptcha.impl.waterripple");
        //⽂字来源
        properties.setproperty(constants.kaptcha_textproducer_char_string, "0123456789");
        config config = new config(properties);
        kaptcha.setconfig(config);
        return kaptcha;
    }
}

实战

我的配置类

获取访问ip和生成md5的工具类

public class commonutil {
    /**
     * 获取ip
     * @param request
     * @return
     */
    public static string
    getipaddr(httpservletrequest request) {
        string ipaddress = null;
        try {
            ipaddress = request.getheader("xforwarded-for");
            if (ipaddress == null ||
                    ipaddress.length() == 0 ||
                    "unknown".equalsignorecase(ipaddress)) {
                ipaddress =
                        request.getheader("proxy-client-ip");
            }
                        request.getheader("wl-proxy-client-ip");
                        request.getremoteaddr();
                if
                (ipaddress.equals("127.0.0.1")) {
                    // 根据⽹卡取本机配置的ip
                    inetaddress inet = null;
                    try {
                        inet =
                                inetaddress.getlocalhost();
                    } catch (unknownhostexception e) {
                        e.printstacktrace();
                    }
                    ipaddress =
                            inet.gethostaddress();
                }
            // 对于通过多个代理的情况,第⼀个ip为客户端真实ip,多个ip按照','分割
            if (ipaddress != null &&
                    ipaddress.length() > 15) {
                // "***.***.***.***".length()
                // = 15
                if (ipaddress.indexof(",") > 0)
                {
                            ipaddress.substring(0, ipaddress.indexof(","));
        } catch (exception e) {
            ipaddress="";
        }
        return ipaddress;
    }
    public static string md5(string data) {
            java.security.messagedigest md =
                    messagedigest.getinstance("md5");
            byte[] array =
                    md.digest(data.getbytes("utf-8"));
            stringbuilder sb = new
                    stringbuilder();
            for (byte item : array) {

                sb.append(integer.tohexstring((item & 0xff) |
                        0x100).substring(1, 3));
            return sb.tostring().touppercase();
        } catch (exception exception) {
        return null;
}

接口开发

@restcontroller
@requestmapping("/api/v1/captcha")
public class captchacontroller {

    @autowired
    private stringredistemplate stringredistemplate;
    
    private producer producer;
    @requestmapping("get_captcha")
    public void getcaptcha(httpservletrequest request, httpservletresponse response){
        string captchatext = producer.createtext();
        string key = getcaptchakey(request);
        // 十分钟过期
        stringredistemplate.opsforvalue().set(key,captchatext,10, timeunit.minutes);
        bufferedimage image = producer.createimage(captchatext);
        servletoutputstream outputstream=null;
        try {
            outputstream= response.getoutputstream();
            imageio.write(image,"jpg",outputstream);
            outputstream.flush();
            outputstream.close();
        } catch (ioexception e) {
            e.printstacktrace();
        }
    }
    /**
     * 生成redis验证码模块的key
     * @param request
     * @return
     */
    private string getcaptchakey(httpservletrequest request){
        string ipaddr = commonutil.getipaddr(request);
        // 请求头
        string useragent=request.getheader("user-agent");
        string key="user_service:captcha:"+commonutil.md5(ipaddr+useragent);
        return key;
}

配置文件

server:
  port: 8080
spring:
  redis:
    host: redis锁在的ip
    password: redis的密码
    port: 端口号
    lettuce:
      pool:
        # 连接池最⼤连接数(使⽤负值表示没有限制)
        max-idle: 10
        # 连接池中的最⼤空闲连接
        max-active: 10
        # 连接池中的最⼩空闲连接
        min-idle: 0
        # 连接池最⼤阻塞等待时间(使⽤负值表示没有限制)
        max-wait: -1ms

结果

Springboot +redis+谷歌开源Kaptcha实现图片验证码功能

到此这篇关于springboot +redis+⾕歌开源kaptcha实现图片验证码功能的文章就介绍到这了,更多相关springboot 图片验证码内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!