Sunday, January 29, 2012

ReCaptcha without plugins

So I'm not that fantastic at reading documentation.  But let's face it.  Coders are not that great at spelling things out.  Exhibit A:

http://code.google.com/apis/recaptcha/docs/verify.html

There is nothing on this API explanation that explains that you can't make this call from javascript.  Although I should have known that putting both public and private keys in JS seems a little insecure.

Ulitimately, you gotta make the reCaptcha verification call from the server-side.  Since I'm a java/spring guy I made a controller that does that.  This is the step that would have been obvious if I just looked more carefully at the example plugins.  But still.

@Controller
public class RecaptchaController {

    public static final String PUBLIC_KEY = "XXX";
    private static final String PRIVATE_KEY = "YYY";
    private static final String RECAPTCHA_URL = "http://www.google.com/recaptcha/api/verify";
   
    @RequestMapping(value="/recaptcha", method=RequestMethod.POST)
    public void checkServer(@RequestParam("remoteip") String remoteip, @RequestParam("challenge") String challenge,
                            @RequestParam("response") String response, HttpServletResponse httpResp){
           
        HttpClient httpClient = new HttpClient();
        PostMethod post = new PostMethod( RECAPTCHA_URL );

        post.addParameter("privatekey", PRIVATE_KEY);
        post.addParameter("remoteip", remoteip);
        post.addParameter("challenge", challenge);
        post.addParameter("response", response);
       
        String resp = "false";
        try {
            httpClient.executeMethod(post);
            resp = getResponseAsString(post);
        } catch (Exception e) {
            resp = "false";
        }
       
        if(resp.startsWith("false")){
            resp = "ERROR";
        }else{
            resp = "SUCCESS";
        }
       
        try {
            OutputStreamWriter writer = new OutputStreamWriter( httpResp.getOutputStream() );
            writer.write(resp);
            writer.close();
        } catch (IOException e) {
            // do nothing
        }
       
    }
   
    private String getResponseAsString(HttpMethod hm) throws IOException {
        InputStream inputStream = hm.getResponseBodyAsStream();

        StringWriter writer = new StringWriter();
        IOUtils.copy(inputStream, writer, "UTF-8");

        return writer.toString();
    }  
}