【问题标题】:How to validate reCAPTCHA V2 Java (Servlet)如何验证 reCAPTCHA V2 Java (Servlet)
【发布时间】:2017-12-03 19:43:48
【问题描述】:

这是一个问答风格的帖子,我将发布问题和答案。主要原因是我花了很多时间寻找最简单的方法来验证 recaptcha V2。因此,我将分享我的知识,以避免进一步浪费开发人员的时间。

如何使用 Java 对 Google reCAPTCHA V2Invisible reCAPTCHA 进行服务器端验证?? p>

【问题讨论】:

    标签: java validation servlets recaptcha invisible-recaptcha


    【解决方案1】:

    我为此使用org.json 库。从here 获取jar 文件或阅读docs。将 jar 文件添加到您的项目中并导入以下类。

    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import org.json.JSONObject;
    

    使用以下方法进行验证。

    /**
     * Validates Google reCAPTCHA V2 or Invisible reCAPTCHA.
     *
     * @param secretKey Secret key (key given for communication between your
     * site and Google)
     * @param response reCAPTCHA response from client side.
     * (g-recaptcha-response)
     * @return true if validation successful, false otherwise.
     */
    public synchronized boolean isCaptchaValid(String secretKey, String response) {
        try {
            String url = "https://www.google.com/recaptcha/api/siteverify",
                    params = "secret=" + secretKey + "&response=" + response;
    
            HttpURLConnection http = (HttpURLConnection) new URL(url).openConnection();
            http.setDoOutput(true);
            http.setRequestMethod("POST");
            http.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded; charset=UTF-8");
            OutputStream out = http.getOutputStream();
            out.write(params.getBytes("UTF-8"));
            out.flush();
            out.close();
    
            InputStream res = http.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(res, "UTF-8"));
    
            StringBuilder sb = new StringBuilder();
            int cp;
            while ((cp = rd.read()) != -1) {
                sb.append((char) cp);
            }
            JSONObject json = new JSONObject(sb.toString());
            res.close();
    
            return json.getBoolean("success");
        } catch (Exception e) {
            //e.printStackTrace();
        }
        return false;
    }
    

    如下图调用上述方法,

    if(isCaptchaValid("enter_your_key_here", request.getParameter("g-recaptcha-response"))){
        //valid
    }
    

    希望这会有所帮助。干杯!


    编辑: 使用POST 方法验证Google 推荐的信息更安全,但是如果您需要GET 方法版本,请参考edit history

    不要对params 变量进行编码。这样做,您将始终得到以下响应。

    {"error-codes":["missing-input-response","missing-input-secret"],"success":false}
    

    【讨论】:

    • 如果您有兴趣接收有关您的代码的评论,也可以在code review site 上发布。
    • 不需要包含远程用户的IP地址吗?
    • 啊,nvm,远程IP是可选的。
    • @Rick 根据您的意愿更改方法。只需在方法中添加另一个参数并将其组合到 url。 :)
    • 我试过你的代码,它可以工作,谢谢。但官方网站(developers.google.com/recaptcha/docs/verify)建议使用 POST 方法。也许使用 POST 更安全。 :)
    【解决方案2】:

    只是为了提供另一种变体:

    import javax.inject.Inject;
    import javax.validation.constraints.NotNull;
    import javax.ws.rs.client.*;
    import javax.ws.rs.core.*;
    
    import org.springframework.stereotype.Component;
    
    import com.fasterxml.jackson.databind.*;
    
    @Component
    public class ReCaptcha {
    
        private final WebTarget webTarget;
    
        public ReCaptcha() {
            webTarget = ClientBuilder.newClient()
                    .target("https://www.google.com/recaptcha/api/siteverify")
                    .queryParam("secret", "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe");
        }
    
        public boolean isValid(@NotNull String token) throws IOException {
            Response response = this.webTarget.queryParam("response", token)
                    .request(MediaType.APPLICATION_JSON)
                    .accept("application/ld+json")
                    .get();
    
            if (response.getStatus() != 200)
                return false;
    
            String stringResponse = response.readEntity(String.class);
            JsonNode jsonNode = new ObjectMapper().readTree(stringResponse);
            return jsonNode.get("success").asBoolean();
        }
    }
    

    此外,您可以验证返回的主机名和操作。 此外,您可能希望记录返回的错误代码。

    您必须用自己的 API 密钥替换使用过的 API 密钥(这是一个测试 API 密钥,应始终返回令牌有效:https://developers.google.com/recaptcha/docs/faq) 将 API 密钥和 API url 放入一个额外的属性文件中也可能是个好主意。

    你可以在任何你喜欢的地方注入这个类。

    我在特殊例外情况下使用它,而不是返回真或假。

    【讨论】:

      猜你喜欢
      • 2015-06-15
      • 2015-11-05
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多