mario741
mario741

Reputation: 189

How do integrate kaptcha in java spring

I need to integrate kaptcha in java spring, on the official website https://code.google.com/p/kaptcha/wiki/SpringUsage is very old information.

Upvotes: 0

Views: 3952

Answers (3)

Szilárd Fodor
Szilárd Fodor

Reputation: 364

There is an open source Spring Boot starter project witch will validate reCAPTCHA for you.

You just have to set the desired URLs (which you want to protect with captcha, e.g.: /api/sign-up) in your config file and this library will check whether the user sent a valid captcha response.

More on GitHub: https://github.com/Mr-DeWitt/spring-boot-recaptcha

Upvotes: 0

Ahmed AL-Tihami
Ahmed AL-Tihami

Reputation: 111

  1. Add the maven dependency:

    <dependency>
        <groupId>com.github.penggle</groupId>
        <artifactId>kaptcha</artifactId>
        <version>2.3.2</version>
    </dependency>
    
  2. Add the kaptcha configurations to the application.properties:

    #Kaptcha 
    kaptcha.config.imageWidth=310
    kaptcha.config.imageHeight=55
    kaptcha.config.textProducerCharString=0123456789aAbBcCdDEeFeGgHhIi
    kaptcha.config.textProducerCharLength=6
    kaptcha.config.headerName=KAPTCHA_HEADER
    kaptcha.config.useBorder=no            
    kaptcha.config.textColor=48,101,137
    
  3. Pickup the configurations using @ConfigurationProperties

    @Data
    @Component
    @ConfigurationProperties(prefix="kaptcha.config")
    public class KaptchaConfigurations{
    private String imageWidth;
    private String imageHeight; 
    private String textProducerCharString;
    private String textProducerCharLength;
    private String headerName;
    private String useBorder;
    private String backgroundClass;
    private String textColor;
    }
    

*if you are not using lombok replace @Data with getters and setters.

  1. Declare Producer @Bean:

    @Bean 
    public Producer createKaptchaProducer(KaptchaConfigurations 
    kaptchaConfigurations) {
    DefaultKaptcha kaptcha = new DefaultKaptcha();
    Properties properties = new Properties();
    properties.put(Constants.KAPTCHA_IMAGE_HEIGHT , 
    kaptchaConfigurations.getImageHeight());
    properties.put(Constants.KAPTCHA_IMAGE_WIDTH, 
    kaptchaConfigurations.getImageWidth());
    properties.put(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH , 
    kaptchaConfigurations.getTextProducerCharLength());
    properties.put(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, 
    kaptchaConfigurations.getTextProducerCharString());
    properties.put(Constants.KAPTCHA_BORDER, 
    kaptchaConfigurations.getUseBorder());
    properties.put(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR,
    kaptchaConfigurations.getTextColor());
    properties.put(Constants.KAPTCHA_NOISE_COLOR,
    kaptchaConfigurations.getTextColor());
    kaptcha.setConfig(new Config(properties));
    return kaptcha;
    }
    
  2. Create an endpoint to get the generated captcha and save the captcha text in the session:

    @GetMapping("/image")
    public void handleRequest(
        HttpServletRequest request,
        HttpServletResponse response) throws Exception {
    response.setDateHeader("Expires", 0);       
    response.setHeader("Cache-Control", 
    "no-store, no-cache, must-        revalidate");     
    response.addHeader("Cache-Control", "post-check=0, pre-check=0");       
    response.setHeader("Pragma", "no-cache");       
    response.setContentType("image/jpeg");
    String capText = captchaProducer.createText();
    request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY,     
    capText);
    
    // create the image with the text
    BufferedImage bi = captchaProducer.createImage(capText);
    
    ServletOutputStream out = response.getOutputStream();
    
    // write the data out
    ImageIO.write(bi, "jpg", out);
    try {
        out.flush();
    } finally {
        out.close();
    }
    }
    
  3. Create an aspect to validate the captcha:

    @Aspect
    @Component
    public class KaptchaAspect {
    
        private KaptchaConfigurations kaptchaConfigurations;
    
        public KaptchaAspect(KaptchaConfigurations kaptchaConfigurations) {
            this.kaptchaConfigurations = kaptchaConfigurations;
        }
    
        @Before("@annotation(ValidateKaptcha)")
        public void validateKaptcha() throws Throwable {         
             String headerName = this.kaptchaConfigurations.getHeaderName();
             HttpServletRequest request =
             ((ServletRequestAttributes)                                                     
             RequestContextHolder
             .currentRequestAttributes())
             .getRequest();
             String headerValue = request.getHeader(headerName);
             String kaptchaSessionValue =     
             request.getSession()
            .getAttribute(Constants.KAPTCHA_SESSION_KEY)
            .toString();
    
           if(headerValue == null || kaptchaSessionValue == null) {          
               throw new BusinessException();
           }
    
           if(!headerValue.equals(kaptchaSessionValue)) {           
              throw new BusinessException();
           }
        }
    }
    
  4. Declare the validation annotation:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ValidateKaptcha {
    }
    
  5. Use the @ValidateKaptcha on top of any endpoint needs to validate the captcha:

    @ValidateKaptcha
    @PostMapping("/forgot-password-by-user-name")
    public ResponseEntity<?> forgotPasswordByUsername(@RequestBody @Valid 
           ForgotPasswordByUsernameInput forgotPasswordByUsernameInput) { 
     ...
    }
    

From the client side pass the kaptcha value in the header, name it KAPTCHA_HEADER.

Upvotes: 2

Abdelghani Roussi
Abdelghani Roussi

Reputation: 2817

You can use reCAPTCHA , follow this tutorial it will help you reCAPTCHA link

Upvotes: 1

Related Questions