首页 > 解决方案 > Android ReCaptcha:未显示复选框

问题描述

我使用Android SafetyNet ReCaptcha在我的 Android 应用程序中显示 Google 验证码。问题是当我测试它时,复选框永远不会显示。相反,验证码显示得很好,它的进度条有点动画,然后它没有任何错误地完成,确认我是一个人。这种行为是正常的,没有任何错误。

但。我想强制验证码,这似乎工作得很好,就像我上面描述的那样,显示复选框。通过“复选框”,我的意思是例如“显示人类用户必须声称通过检查来识别的人行横道的复选框”。官方文档没有解释怎么做:https ://developer.android.com/training/safetynet/recaptcha#send-request

资源(文档和 StackOverflow)

我已遵循此文档:https ://developer.android.com/training/safetynet/recaptcha#send-request 。但是,它没有提供有关如何解决我的问题的任何信息。

我还没有找到任何相关的问题。事实上,我没有发现任何关于如何为 Android 实现 ReCaptcha 的问题,除了一个非常短的问题(它没有提供任何有用的数据来解决我的问题)。

我的实现

我将向你展示我是如何实现他们的 API ReCaptcha for Android (SafetyNet ReCaptcha) 来帮助你的。

过程

  1. 我的应用程序的用户可以注册、登录、退出。

  2. 当用户启动我的应用程序时,会出现一个闪屏。如果用户未连接,则邀请他触摸按钮。

    2.1。如果他触摸按钮,就会启动 ReCaptcha。

    2.1.1. If the ReCaptcha is successfully completed, then the user can sign-up and sign-in with his Google account (I use Google Firebase Auth and even AuthUI).
    
    2.1.2. Otherwise, nothing occurs : he'll have to re-try to complete ReCaptcha.
    

来源

SplashScreen.java(一个AppCompatActivity类):监听按钮上的“触摸”事件的“onClick”事件处理程序

在简历中:我将监听器附加到按钮上。因此,如果单击后者,我会调用verifyWithRecaptcha(synchrone! 并且它是自愿的) Executor。然后我打电话给谷歌的服务器,以确保验证码是由人类完成的,而不是机器人完成的,这要感谢我的班级NetworkUseRecaptcha提供了result谷歌的服务器。

    final Context that = this;
    button_splash_screen_recaptcha.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            final Executor executor = new Executor() {
                @Override
                public void execute(@NonNull Runnable command) {
                    command.run();
                }
            };

            executor.execute(new Runnable() {
                @Override
                public void run() {
                    SafetyNet.getClient(that).verifyWithRecaptcha("PUBLIC KEY")
                            .addOnSuccessListener(executor,
                                    new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
                                        @Override
                                        public void onSuccess(final SafetyNetApi.RecaptchaTokenResponse response) {
                                            String userResponseToken = response.getTokenResult();
                                            if (!userResponseToken.isEmpty()) {
                                                String[] parameters = new String[2];
                                                parameters[0] = "SECRET KEY";
                                                parameters[1] = userResponseToken;
                                                new NetworkUseRecaptcha(new RecaptchaPostExecuteCallback() {
                                                    @Override
                                                    public void onTaskCompleted(String result, boolean background_error) {
                                                        if(background_error) {
                                                            runOnUiThread(new Runnable() {
                                                                public void run() {
                                                                    Toast.makeText(that,"Error N°2: Unable to check the captcha.", Toast.LENGTH_SHORT).show();
                                                                }
                                                            });
                                                            return;
                                                        }

                                                        try {
                                                            final JSONObject json_response = new JSONObject(result);
                                                            if(!json_response.isNull("success") && json_response.getBoolean("success")) {
                                                                final List<AuthUI.IdpConfig> providers = ImmutableList.of(
                                                                        new AuthUI.IdpConfig.GoogleBuilder().build()
                                                                );
                                                                startActivityForResult(
                                                                        AuthUI.getInstance()
                                                                                .createSignInIntentBuilder()
                                                                                .setAvailableProviders(providers)
                                                                                .setAlwaysShowSignInMethodScreen(true)
                                                                                .setLogo(R.drawable.yellow_logo)
                                                                                .setTheme(R.style.LoginTheme)
                                                                                .build(),
                                                                        REQUEST_CODE_SIGN_IN
                                                                );

                                                            } else {
                                                                Toast.makeText(that,"Error N°4: Unable to check the captcha.", Toast.LENGTH_SHORT).show();
                                                            }
                                                        } catch (JSONException e) {
                                                            runOnUiThread(new Runnable() {
                                                                public void run() {
                                                                    Toast.makeText(that,"Error N°3: Unable to check the captcha.", Toast.LENGTH_SHORT).show();
                                                                }
                                                            });
                                                        }
                                                    }
                                                }).execute(parameters);
                                            }
                                        }
                                    })
                            .addOnFailureListener(executor, new OnFailureListener() {
                                @Override
                                public void onFailure(@NonNull Exception e) {
                                    System.err.println(e);
                                    runOnUiThread(new Runnable() {
                                        public void run() {
                                            Toast.makeText(that,"Error N°1: Unable to check the captcha.", Toast.LENGTH_SHORT).show();
                                        }
                                    });
                                }
                            });
                }
            });
        }
    });

NetworkUseRecaptcha.java:我的类允许我联系 Google 的服务器以验证验证码

class NetworkUseRecaptcha extends AsyncTask<String, Void, String> {
    private final RecaptchaPostExecuteCallback post_execute_callback;
    private boolean background_error;

    NetworkUseRecaptcha(RecaptchaPostExecuteCallback post_execute_callback) {
        this.post_execute_callback = post_execute_callback;
        background_error = false;
    }

    @Override
    protected String doInBackground(String[] parameters) {
        StringBuilder string_builder = new StringBuilder();

        try {
            URL url = new URL("https://www.google.com/recaptcha/api/siteverify");
            HttpsURLConnection https_url_connection = (HttpsURLConnection) url.openConnection();
            https_url_connection.setRequestMethod("POST");
            https_url_connection.setDoOutput(false);
            https_url_connection.setUseCaches(false);

            OutputStream os = https_url_connection.getOutputStream();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8));
            writer.write("secret=" + parameters[0] + "&response=" + parameters[1]);
            writer.flush();
            writer.close();
            os.close();

            InputStream input_stream = https_url_connection.getInputStream();
            BufferedReader buffered_reader = new BufferedReader(new InputStreamReader(input_stream));
            String line;
            while((line = buffered_reader.readLine()) != null) {
                string_builder.append(line);
            }
            buffered_reader.close();

        } catch (Exception e) {
            background_error = true;
        }

        return string_builder.toString();
    }

    @Override
    protected void onPostExecute(String result) {
        post_execute_callback.onTaskCompleted(result, background_error);
    }
}

标签: androidrecaptcha

解决方案


https://developers.google.com/android/reference/com/google/android/gms/safetynet/SafetyNetClient#verifyWithRecaptcha(java.lang.String):“如果 reCAPTCHA 确信这是真实设备上的真实用户它将返回一个没有挑战的令牌。否则它将在返回令牌之前提供视觉/音频挑战来证明用户的人性。”

所以我的愿望是不可能具体化的......


推荐阅读