验证码

最近在工作中做到这一部分,所以在这里记录一下。

首先我们整理一下思路。

一开始,我做这个验证码的时候,只是在服务器端生成一个bufferedImage,记录下验证码 的code,并存入到redis中,然后用通过servletResponse写出去。

但是后来却发现多人验证的话,会分不清验证码,因为存入redis里的key是写死的,导致登陆不了。

然后就决定,用每一个ID对应一个验证码,ID作为key将验证码的值存入到redis中。这样多人验证就不会乱了。服务器生成 ID(这里不考虑ID重复的问题)和Image传递给前端。

前端获取ID是为了到服务器取到redis里正确的验证码,来跟用户输入的进行比较。Image是为了展示验证码图片。

这里我引入了kaptcha来生成验证码。

1.在POM文件中引入kaptcha

<dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
</dependency>

2.在springmvc里配置验证码的bean

<bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha">
        <property name="config">
            <bean class="com.google.code.kaptcha.util.Config">
                <constructor-arg>
                    <props>
                        <prop key="kaptcha.border">yes</prop>
                        <prop key="kaptcha.border.color">105,179,90</prop>
                        <prop key="kaptcha.textproducer.font.color">blue</prop>
                        <prop key="kaptcha.image.width">125</prop>
                        <prop key="kaptcha.image.height">45</prop>
                        <prop key="kaptcha.textproducer.font.size">45</prop>
                        <prop key="kaptcha.session.key">code</prop>
                        <prop key="kaptcha.textproducer.char.length">4</prop>
                        <prop key="kaptcha.textproducer.font.names">微软雅黑</prop>
                    </props>
                </constructor-arg>
            </bean>
        </property>
    </bean>

3.编写验证码服务类和实现类

public interface kaptchaService {

    CaptchaDTO createCaptcha();
}
@Service
public class kaptchaServiceImpl implements kaptchaService {

    private static final int SESSION_TIME = 60*30;
    @Autowired
    private Producer captchaProducer;

    @Override
    public CaptchaDTO createCaptcha() {
        String captchaId = UUID.randomUUID().toString().replace("-", "");
        String capText = captchaProducer.createText();
        BufferedImage bi = captchaProducer.createImage(capText);
        // 将验证码保存到redis中;
        RedisUtil.del("captcha_code_"+captchaId);
        RedisUtil.setex("captcha_code_"+captchaId,capText.toLowerCase(),SESSION_TIME);

        CaptchaDTO captchaDTO = new CaptchaDTO();
        captchaDTO.setCaptchaId(captchaId);
        captchaDTO.setCode(capText);
        captchaDTO.setImage(bi);
        return captchaDTO;
    }
}

4.编写控制器和映射

@Controller
public class CodeController {

    @Autowired
    private kaptchaService kaptchaService;

    @ResponseBody
    @RequestMapping("/captcha")
    public BizResult getCode(){
        // 定义图像buffer
        CaptchaDTO captchaDTO = kaptchaService.createCaptcha();
        try {
            CaptchaModel captchaModel = new CaptchaModel();
            captchaModel.setCaptchaId(captchaDTO.getCaptchaId());
            captchaModel.setImage("data:image/.jpg;base64," + imageToBase64(captchaDTO.getImage()));
            return BizResult.success(captchaModel);
        } catch (Exception e) {
            return BizResult.fail("网络异常");
        }
    }

    /**
     * 图片进行base64编码
     * @param bufferedImage 图片流
     * @return string
     */
    private static String imageToBase64(BufferedImage bufferedImage) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", outputStream);
        String base64 = Base64.getEncoder().encodeToString(outputStream.toByteArray());
        return base64.replace("\n", "");
    }
}

5.前端


<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<h2>验证码</h2>
            <label>
                <input style="float: left; margin-right: 10px;"  type="text" name="validate" id="validate"  class="txt_input3" >
            </label>
            <label>
                <img id="captchaImage" class="txt_input3" src="${ctx}/captcha" onclick="changeImg()"/>
            </label>
function getValidateCode(url){
    $.ajax({
        type:"GET",
        url:"/captcha",
        success:function (ret){
             $("#captchaImage").attr("src",ret.data.image);
             rediskey = ret.data.captchaId;
        }
    });
}

 

posted @ 2019-01-10 15:43  苏打水了面包  阅读(416)  评论(0编辑  收藏  举报