如何验证 reCAPTCHA V2 Java (Servlet)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47622506/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:42:30  来源:igfitidea点击:

How to validate reCAPTCHA V2 Java (Servlet)

javavalidationservletsrecaptchainvisible-recaptcha

提问by Roshana Pitigala

This is an Q&A style post, which I'll post both the question and an answer. The main reason for this is that I spent quite a lot of time searching the easiest way to validate recaptcha V2. So I'm going to share my knowledge to avoid further time wastage of developers.

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

How to do a server side validationof Google reCAPTCHA V2or Invisible reCAPTCHAwith Java?

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

回答by Roshana Pitigala

I'm using org.jsonlibrary for this. Get the jarfile from hereor read the docs. Add the jar file to your project and import the following classes.

我正在org.json为此使用库。jar这里获取文件或阅读文档。将 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;

Use the following method for validation.

使用以下方法进行验证。

/**
 * 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;
}

Call the above method as shown below,

调用上面的方法如下图,

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

Hope this helps. Cheers!

希望这可以帮助。干杯!



EDIT:Using the POSTmethod to verify information as recommended by Google, is way more safer, however if you need the GETmethod version please refer the edit history.

编辑:使用谷歌POST推荐的方法验证信息更安全,但是如果您需要方法版本,请参阅编辑历史记录GET

Don't encode the paramsvariable. You will always get the below response by doing so.

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

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

回答by Spenhouet

Just to provide another variant:

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

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.Hymanson.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();
    }
}

In addition you could validate the returned hostname and action. Also you might want to log returned error codes.

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

You will have to replace the used API key with your own (this is a test API key and should always return that the token is valid: https://developers.google.com/recaptcha/docs/faq) It also might be a good idea to put the API key and API url into a extra property file.

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

You can inject this class everywhere you like.

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

I use it with special exceptions instead of returning true or false.

我在特殊情况下使用它,而不是返回 true 或 false。

回答by David

For use with webmail scripts and comment boxes:

用于网络邮件脚本和评论框:

if(isCaptchaValid("secret", request.getParameter("g-recaptcha-response"))){
  request.setAttribute("Captcha", "true");
try {
  Mailserver.sendEmail(host, port, user, pass, recipient, subject, name, email, content);
  resultMessage = "The e-mail is sent successfully!";
  getServletContext().getRequestDispatcher("/captchacorrect.jsp").forward(request, response);
} catch (Exception ex) {
  ex.printStackTrace();
  resultMessage = "An error occured: " + ex.getMessage();
} finally {
  request.setAttribute("Message", resultMessage);
}
} else {
    getServletContext().getRequestDispatcher("/captchawrong.jsp").forward(request, response);
  } }