0

I'm using SimpleCaptcha to secure our contact form. It works well, but only after reloading the page.

The Servlet is nl.captcha.servlet.StickyCaptchaServlet, so it should not change the image after reloads. But when first opening the page the image is just not loaded. However, after reloading everything works fine.

the web.xml

The captcha is served by an application running at /services.

<web-app>
  <servlet>
    <servlet-name>captcha</servlet-name>
    <servlet-class>nl.captcha.servlet.StickyCaptchaServlet<servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>captcha</servlet>
    <url-pattern>/captcha.png</url-pattern>
  </servlet-mapping>
</web-app>

the html

<img src="/services/captcha.png">

the server

I'm using tomcat-7.0.34 on a Windows 7 64bit machine with Java 1.7.0_07.

the question

Why does the image only show up after a reload? Any ideas?

Roman C
  • 49,761
  • 33
  • 66
  • 176
Dominik Schreiber
  • 2,629
  • 1
  • 23
  • 33
  • your `StickyCaptchaServlet` is configured to `/captcha.png` and you using in html page `/services/captcha.jpg` is this real or just typo mistake? Do you have any other `Servlet` for this application? What is your `` configuration? – Michał Kupisiński Jan 23 '13 at 13:06
  • My fault, I copied it wrong... edited it in the question. I have two other servlets, both for contact forms, both checking if the captcha is solved. Currently there is no ```` configuration. – Dominik Schreiber Jan 23 '13 at 13:11
  • try to add `` and set for your captcha server bigger value than for other servlets which are using that captcha – Michał Kupisiński Jan 23 '13 at 13:12
  • I tried it, but that doesn't work. Even if I access the servlet directly (at ``localhost:8080/services/captcha.png`` for example) it needs a reload to show the captcha. – Dominik Schreiber Jan 23 '13 at 13:22

4 Answers4

2

there are several steps you can follow:

1> modify web.xml add your servlet that extends nl.captcha.servlet.StickyCaptchaServlet class

 <servlet>   
    <description></description>    
    <display-name>CustomCaptchaServlet</display-name>    
    <servlet-name>CustomCaptchaServlet</servlet-name>    
    <servlet-class>org.example.servlets.CustomCaptchaServlet</servlet-class>    
 </servlet>    
  <servlet-mapping>    
    <servlet-name>CustomCaptchaServlet</servlet-name>    
    <url-pattern>/CustomCaptchaServlet</url-pattern>    
  </servlet-mapping>

2> CustomCaptchaServlet.java

package org.example.servlets;    
import static nl.captcha.Captcha.NAME;    

import java.io.IOException;    

import javax.servlet.ServletException;    
import javax.servlet.http.HttpServlet;    
import javax.servlet.http.HttpServletRequest;    
import javax.servlet.http.HttpServletResponse;    
import javax.servlet.http.HttpSession;    

import nl.captcha.Captcha;    
import nl.captcha.servlet.CaptchaServletUtil;    
import nl.captcha.servlet.StickyCaptchaServlet;    

public class CustomCaptchaServlet extends StickyCaptchaServlet {    
    private static final long serialVersionUID = 1L;    

    /**
     * @see StickyCaptchaServlet#StickyCaptchaServlet()
     */
    public CustomCaptchaServlet() {
        super();
        // TODO Auto-generated constructor stub
    }


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    

        String _width = getServletConfig().getInitParameter("width");    
        String _height = getServletConfig().getInitParameter("height");    
        HttpSession session = request.getSession();    
        Captcha captcha;    
        if (session.getAttribute(NAME) == null) {    
            captcha = new Captcha.Builder(Integer.parseInt(_width), Integer.parseInt(_height))    
            .addText()    
            .gimp()    
            .addBorder()    
                .addNoise()    
                .addBackground()    
                .build();    
            session.setAttribute(NAME, captcha);    
            CaptchaServletUtil.writeImage(response, captcha.getImage());    
            return;    
        }    
        captcha = (Captcha) session.getAttribute(NAME);    
        CaptchaServletUtil.writeImage(response, captcha.getImage());    
    }    


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    

    }    

}    
Maciej Dobrowolski
  • 11,561
  • 5
  • 45
  • 67
0

Check that the web.xml has captcha.png while the HTML is referring to captcha.jpg.

Does that solve the issue?

TechSpellBound
  • 2,505
  • 6
  • 25
  • 36
0

The problem is that StickyCaptchaServlet is creating new captcha image for session. When you make initial request to a page you have no session id so StickyCaptchaServlet cannot connect you to any image created for a particular session.

After first request main servlet create session for you and send you back some kind of sessionId. With next request (also reload) you send to server request with recevied previously sessionId so now your StickyCaptchaServlet is possible to collect captcha image for your session because it knows that you are in any session.

Do you understand this explanation? Will it be helpfull for you?

Added after your question to resolve this problem.

You can add to your web app class which will implements HttpSessionListener. Then, in method sessionCreated you can add request to StickyCaptchaServlet with just created sessionId. According to StickyCaptchaServlet doc You just have to invoke doGet method of it with passed sessionId key. After that - when browser on your page will request for url /services/captcha.png it should get as response image created and prepared just before it by your HttpSessionListener implementation.

Other way is to use cliend side scripting and after page is loaded, with no image at all, just reload it - as this internal reload, for example JavaScript, the browser will know sessionId and will pass it through the request for captcha image. By reload I mean only reload image, not the whole page.

Will any of those suggestions resolve your problem? Give me a feedback about it.

Michał Kupisiński
  • 3,765
  • 1
  • 19
  • 23
  • This explanation seems to adress my real problem. But is there any solution? (i.e. could I generate the session with a corresponding `sessionId` with the first page call?) – Dominik Schreiber Jan 23 '13 at 21:24
  • Thanks for your suggestions. I tried client-side reloading of the image (re-setting the ``src`` attribute, adding a dummy value to force reload), but that does not work. Reloading the full page does not seem feasible to me. The ``HttpSessionListener`` thing sounds interesting, but I can't get it to call the ``doGet`` method of the ``StickyCaptchaServlet``. – Dominik Schreiber Jan 28 '13 at 13:18
0

Just do this way to by pass what emka86 had said.

<img src="/services/captcha.png" style="display:none"> (Duplicate part to fix the issue)

<img src="/services/captcha.png"> (The actual one)

Hope this helps for any future developer out there.

  • While I ended up patching SimpleCaptcha myself (and tbh I forgot what I did exactly) this is a quite simple solution that I really like. Thanks! – Dominik Schreiber Apr 02 '14 at 11:31
  • @Nilindra, what if I am using **** ?? Here "captchaImage" is mapped to a servlet in **web.xml** which return the actual captcha image. I am also facing similar issue. Any help would be appreciated – NIKHIL CHAURASIA Dec 05 '16 at 05:57