9

We are trying to build a jmeter testcase which does the following:

  • login to a system
  • obtain some information and check whether correct.

Where we are facing issues is because there is a captcha while logging into the system. What we had planned to do was to download the captcha link and display, and wait for user to type in the value. Once done, everything goes as usual.

We couldnt find any plugin that can do the same? Other than writing our own plugin, is there any option here?

Koran
  • 647
  • 2
  • 8
  • 21

3 Answers3

8

I was able to solve it myself. The solution is as follows:

  • Create a JSR223 PostProcessor (using Groovy)
  • more practical CAPTCHA example with JSESSIONID handling and proxy setting
  • using image.flush() to prevent stale CAPTCHA image in dialog box

JSR223 Parameters for proxy connection setting:

Parameters: proxy 10.0.0.1 8080

In it, the following code displays the captcha and waits for user input

                import  java.awt.Image;
                import  java.awt.Toolkit;
                import  javax.swing.Icon;
                import  javax.swing.JOptionPane;
                
                import org.apache.jmeter.threads.JMeterContextService;
                import org.apache.jmeter.threads.JMeterContext;
                import org.apache.jmeter.protocol.http.control.CookieManager;  
                import org.apache.jmeter.protocol.http.control.Cookie;

                URL urlTemp ;
                urlTemp = new URL( "https://your.domainname.com/endpoint/CAPTCHACode"); 
                HttpURLConnection myGetContent = null;
                if(args[0]=="proxy" ){
                   Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(args[1], Integer.parseInt(args[2])));
                   myGetContent = (HttpURLConnection) urlTemp.openConnection(proxy);
                }else{
                       myGetContent = (HttpURLConnection) urlTemp.openConnection();
                } 
                // false for http GET
                myGetContent.setDoOutput(false);
                myGetContent.connect();
                int status = myGetContent.getResponseCode();
                log.info("HTTP Status Code: "+Integer.toString(status));
                if (status == HttpURLConnection.HTTP_OK) {
                    //We have 2 Set-Cookie headers in response message but 1 Set-Cookie entry in Map
                    String[] parts2;        
                    for (Map.Entry<String, List<String>> entries : myGetContent.getHeaderFields().entrySet()) {
                           if( entries.getKey()  == "Set-Cookie"   ){
                            for (String value : entries.getValue()) {
                               if ( value.contains("JSESSIONID") == true   ){
                                     String[] parts = value.split(";",2);
                                     log.info("Response header: "+ entries.getKey() + " - " +  parts[0] );
                                     JMeterContext context = JMeterContextService.getContext();
                                     CookieManager manager = context.getCurrentSampler().getCookieManager();
                                     parts2 = parts[0].split("=",2)
                                     Cookie cookie = new Cookie("JSESSIONID",parts2[1],"your.domainname.com","/endpoint",true,0, true, true, 0);
                                     manager.add(cookie);
                                     log.info( cookie.toString() );
                                     log.info("CookieCount "+ manager.getCookieCount().toString() );
                                }
                            }                                            
                            }
                       }//end of outer for loop
                           if ( parts2.find() == null ) {
                              throw new Exception("The Response Header not contain Set-Cookie:JSESSIONID=  .");
                          }         
                }else{
                        throw new Exception("The Http Status Code  was ${status} , not expected 200 OK.");
                }
                BufferedInputStream bins = new BufferedInputStream(myGetContent.getInputStream());
                String destFile = "number.png";
                File f = new File(destFile);
                if(f.exists() ) {                         
                    boolean fileDeleted =  f.delete();
                    log.info("delete file ... ");  
                    log.info(String.valueOf(fileDeleted));
                }
                FileOutputStream fout =new FileOutputStream(destFile);
                int m = 0;
                byte[] bytesIn = new byte[1024];
                while ((m = bins.read(bytesIn)) != -1) {
                    fout.write(bytesIn, 0, m);
                }
                fout.close();
                bins.close();
                log.info("File " +destFile +" downloaded successfully");                               
                Image   image = Toolkit.getDefaultToolkit().getImage(destFile);
                image.flush(); // release the prior cache of Captcha image
                Icon icon = new javax.swing.ImageIcon(image);
                JOptionPane pane = new JOptionPane("Enter Captcha", 0, 0, null);
                String captcha = pane.showInputDialog(null, "Captcha", "Captcha", 0, icon, null, null);
                captcha = captcha.trim();
                captcha = captcha.replaceAll("\r\n", "");
                log.info(captcha);                 
                vars.put("captcha", captcha);
                myGetContent.disconnect();

By vars.put method we can use the captcha variable in any way we want. Thank you everyone who tried to help.

Koran
  • 647
  • 2
  • 8
  • 21
6

Since CAPTHA used to detect non-humans, JMeter will always fail it.

You have to make a workaround in your software: either disable captcha requesting or print somewhere on page correct captcha. Of course, only for JMeter tests.

Andrey Pokhilko
  • 2,578
  • 18
  • 19
3

Dirty workaround? Print the captcha value in alt image for the tests. And then you can retrieve the value and go on.

Syl
  • 3,719
  • 6
  • 35
  • 59