基于google插件Kaptcha实现图片验证码功能

    xiaoxiao2021-12-14  57

    Kaptcha是谷歌的一个验证码插件,通过引入maven依赖的jar便可以使用到我们的项目中,当然生成验证码也必然要验证是否正确,我的实现是在生成验证码时把验证码存到redis中,验证时通过key从redis中取出验证码和用户输入的验证码对比是否正确。

    maven依赖:

    <!--https://mvnrepository.com/artifact/com.github.penggle/kaptcha -->

    <dependency>

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

        <artifactId>kaptcha</artifactId>

        <version>2.3.2</version>

    </dependency>

     

    然后将生成验证与验证封装到一个service,

    public interface IdentifyService{

     

        /**

         * 获取验证码

         * @return

        */

        String getCode(String key, HttpServletRequest req, HttpServletResponseresp) throws ServletException,IOException;

     

        /**

         * 验证验证码

         * @return

        */

        boolean verifyCode(String key, String code);

     

    }

     

    实现:

    @Service

    public class IdentifyServiceImplextends KaptchaServlet implements IdentifyService {

     

        private Logger logger= LogManager.getLogger(IdentifyServiceImpl.class);

     

        @Autowired

        private RedisService redisService;

     

        @Override

        public String getCode(String key,HttpServletRequest req, HttpServletResponse resp) throwsServletException,IOException{

           super.init(initServletConfig(req));

           super.doGet(req,resp);

           String code = (String) req.getSession().getAttribute("KAPTCHA_SESSION_KEY");

           redisService.setObject(key,code);

           logger.info("save code to redis ! key : {}, code : {}",key,code);

           return code;

        }

     

        @Override

        public boolean verifyCode(String key,String code){

           String redisCode = redisService.getObject(key);

           redisService.remove(key);

           if(StringUtils.isBlank(redisCode)){

               return false;

           }

           logger.info("get right code from redis ! key : {}, code : {}",key,redisCode);

           return redisCode.equals(code)?true : false;

        }

     

        private ServletConfiginitServletConfig(HttpServletRequest req){

           ServletConfig servletConfig = new ServletConfig() {

               @Override publicString getServletName() {

                  // return req.getSession().getServletContext().getServletContextName();

                   return null;

               }

     

               @Override publicServletContext getServletContext() {

                    returnreq.getSession().getServletContext();

               }

     

               @Overridepublic StringgetInitParameter(String s) {

                    //returnreq.getSession().getServletContext().getInitParameter(s);

                   return null;

               }

     

               @Override publicEnumeration<String>getInitParameterNames() {

                    returnreq.getSession().getServletContext().getInitParameterNames();

               }

           };

           return servletConfig;

        }

     

    }

    低版本的Kaptcha有kaptchaProducer的默认实现,直接调用doGet()方法即可,但是高版本为了能让用户自定义验证码的属性,必须先调.init()方法实例化kaptchaProducer,所以需要自己实例化一个servletConfig,再调用.init()方法实例化kaptchProducer

     

    redis的封装:

    public interface RedisService{

     

       <K,V> void setObject(K key, V value);

     

       <K,V> V getObject(K key);

     

       <K> void remove(K key);

     

       <K> void removeAll(K ... keys);

    }

    实现:

    @Service

    public class RedisServiceImplimplements RedisService {

     

        private Logger logger= LogManager.getLogger(RedisServiceImpl.class);

     

        @Autowired

        private RedisTemplate redisTemplate;

     

        @Override

        public <K,V> void setObject(K key, V value){

           redisTemplate.opsForValue().set(key,value);

           logger.info("set to redis success!");

        }

     

        @Override

        public <K,V> V getObject(K key){

            V value = (V)redisTemplate.opsForValue().get(key);

           logger.info("get value from redis result: {}",value);

           return value;

        }

     

        @Override

        public <K> void remove(K key){

           redisTemplate.delete(key);

           logger.info("delete from redis success!");

        }

     

        @Override

        public <K> void removeAll(K ... keys){

           redisTemplate.delete(Arrays.asList(keys));

           logger.info("delete all from redis success!");

        }

    }

    controller层获取验证码与验证接口:

    @RestController

    @RequestMapping("/identifyCode")

    public class IdentifyCodeController{

     

        private static final String INDENTIFY_CODE ="identify_code_register:%s";

        private Logger logger= LogManager.getLogger(IdentifyCodeController.class);

        @Autowired

        private IdentifyService identifyService;

     

        @Autowired

        private ResponseHolder responseHolder;

     

        @RequestMapping(value = "generate", method = RequestMethod.GET)

        public void generateCode(String mobile,HttpServletRequest req, HttpServletResponse resp){

           try {

               String code = identifyService.getCode(String.format(INDENTIFY_CODE, mobile), req, resp);

               logger.info("get verify code ! mobile : {}, code : {}",mobile,code);

           }catch (Exceptione){

               logger.error("get verify code error! mobile : {}",mobile);

           }

        }

     

        @RequestMapping(value = "verify", method = RequestMethod.POST)

        public void verifyCode(String mobile, String code){

           boolean result= identifyService.verifyCode(String.format(INDENTIFY_CODE, mobile),code);

           if(result){

               logger.info("验证通过 ! mobile : {}, code :{}",mobile,code);

           }else {

               logger.info("验证不通过 ! mobile : {}, code: {}",mobile,code);

               responseHolder.setErrorMsg(ErrorMsg.VERIFY_CODE_ERROR);

           }

        }

       

    }

    其中的ResponseHolder是对controller返回结果的统一处理。我们此处不论。有兴趣去https://github.com/feixiaobo/exercise这里看一下。值得注意的是,我所采用的是spring-boot的架构,所以redis的实现化与注入是spring-boot自己完成的,和spring的jdbcTemplate一个原理,配置文件中配置好属性,直接注入RedisTemplate即可。

    转载请注明原文地址: https://ju.6miu.com/read-970788.html

    最新回复(0)