如何解决Android WebView中reCAPTCHA重复验证10-20次的问题
解决Android WebView中Google reCAPTCHA重复验证的问题
我来帮你搞定这个头疼的reCAPTCHA重复验证问题~ 之所以WebView每次打开都要反复验证10-20次,而Chrome只需要一次,核心原因是WebView的默认配置没有让reCAPTCHA识别并持久化你的验证状态,比如Cookie、本地存储、浏览器标识这些关键信息没配置到位。结合你的代码,我给你整理了具体的解决方案:
关键问题分析与修复步骤
1. 正确配置Cookie(尤其是第三方Cookie)
reCAPTCHA的验证状态依赖Cookie持久化,而你当前的Cookie配置有两个明显问题:
- Android 5.0(API 21)及以上版本,需要单独开启第三方Cookie支持,否则reCAPTCHA的跨域Cookie无法被保存
CookieSyncManager在API 21之后已经废弃,改用CookieManager.flush()来确保Cookie持久化到本地
修改后的Cookie配置代码:
CookieManager cookieManager = CookieManager.getInstance(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // 启用第三方Cookie支持,这是reCAPTCHA保存状态的关键 cookieManager.setAcceptThirdPartyCookies(web, true); } else { cookieManager.setAcceptCookie(true); } // 强制将Cookie持久化到本地 cookieManager.flush();
2. 调整User-Agent,贴近Chrome移动端
你当前用的是非常旧的Chrome User-Agent(Chrome 18),reCAPTCHA可能会把WebView识别为陌生/过时的浏览器,从而强制重复验证。建议用系统自带的Chrome User-Agent,或者更接近当前版本的:
// 方式1:获取系统Chrome的原生User-Agent String chromeUserAgent = web.getSettings().getUserAgentString(); web.getSettings().setUserAgentString(chromeUserAgent); // 方式2:直接设置一个较新的移动端Chrome UA web.getSettings().setUserAgentString("Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36");
3. 启用缓存与本地存储,让验证状态持久化
你当前设置了LOAD_NO_CACHE,这会导致WebView每次都重新加载页面,完全无法保留reCAPTCHA的验证状态。同时要确保DOM Storage、数据库存储的配置正确:
WebSettings webSettings = web.getSettings(); // 改用默认缓存策略,允许缓存验证状态 webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // 启用DOM Storage(reCAPTCHA会用它存储验证会话) webSettings.setDomStorageEnabled(true); // 启用数据库存储 webSettings.setDatabaseEnabled(true); // 设置数据库存储路径,确保App有权限写入 String databasePath = getApplicationContext().getFilesDir().getPath() + "/databases"; webSettings.setDatabasePath(databasePath); // 启用App缓存 webSettings.setAppCacheEnabled(true); webSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath());
4. 修正代码中的语法错误与废弃API
你的代码里有几处语法问题(比如WebChromeClient的括号未闭合),还有废弃的CookieSyncManager调用,我已经在修正后的完整代码里统一处理了。
完整修正后的代码示例
static boolean ASWP_CAMUPLOAD = SmartWebView.ASWP_CAMUPLOAD; static boolean ASWP_ONLYCAM = SmartWebView.ASWP_ONLYCAM; static boolean ASWP_MULFILE = SmartWebView.ASWP_MULFILE; private static String ASWV_F_TYPE = SmartWebView.ASWV_F_TYPE; private String asw_cam_message; private ValueCallback<Uri> asw_file_message; private ValueCallback<Uri[]> asw_file_path; private final static int asw_file_req = 1; private final static int file_perm = 2; private static final String TAG = MainActivity.class.getSimpleName(); // 改用贴近当前Chrome的User-Agent public static final String USER_AGENT = "Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"; @SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"}) @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_vtop); AndroidNetworking.initialize(getApplicationContext()); WebView web = findViewById(R.id.web); ProgressBar progressBar = findViewById(R.id.progressBar); ActionBar ab = getSupportActionBar(); assert ab != null; ab.setElevation(0); checkConnection(); if (Build.VERSION.SDK_INT < 18) { web.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { web.setLayerType(View.LAYER_TYPE_HARDWARE, null); } else { web.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } WebSettings webSettings = web.getSettings(); // 设置User-Agent webSettings.setUserAgentString(USER_AGENT); // 调整缓存策略,允许保留验证状态 webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // 启用DOM Storage和数据库存储 webSettings.setDomStorageEnabled(true); webSettings.setDatabaseEnabled(true); String databasePath = getApplicationContext().getFilesDir().getPath() + "/databases"; webSettings.setDatabasePath(databasePath); // 启用App缓存 webSettings.setAppCacheEnabled(true); webSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath()); webSettings.setJavaScriptEnabled(true); webSettings.setUseWideViewPort(true); webSettings.setSupportZoom(true); webSettings.setSaveFormData(true); webSettings.setAllowContentAccess(true); webSettings.setLoadWithOverviewMode(true); webSettings.setSupportMultipleWindows(true); // 正确配置Cookie CookieManager cookieManager = CookieManager.getInstance(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { cookieManager.setAcceptThirdPartyCookies(web, true); } else { cookieManager.setAcceptCookie(true); } cookieManager.flush(); web.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { return super.onJsAlert(view, url, message, result); } }); web.setWebViewClient(new WebViewClient() { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { progressBar.setVisibility(View.VISIBLE); super.onPageStarted(view, url, favicon); web.setVisibility(View.INVISIBLE); } @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { web.loadUrl("about:blank"); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { progressBar.setVisibility(View.VISIBLE); view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); web.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); // 用flush替代废弃的CookieSyncManager CookieManager.getInstance().flush(); } }); progressBar.setMax(100); web.setDownloadListener(new DownloadListener() { @Override public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) { // 这里可以添加自定义下载逻辑 } }); registerForContextMenu(web); if (savedInstanceState == null) { web.post(new Runnable() { @Override public void run() { web.loadUrl("https://vtop.vitap.ac.in/vtop/login?logout/"); } }); } } // 检查网络连接状态 protected boolean isOnline() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); assert cm != null; NetworkInfo netInfo = cm.getActiveNetworkInfo(); return netInfo != null && netInfo.isConnectedOrConnecting(); } public void checkConnection() { if (!isOnline()) { web.setVisibility(View.INVISIBLE); final AlertDialog.Builder builder = new AlertDialog.Builder(VTOP.this); builder.setTitle("Connection"); builder.setMessage("Make sure you are connected to Internet or College Wi-Fi"); builder.setCancelable(false); builder.setNegativeButton("Back", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); finish(); } }); builder.setPositiveButton("Reload", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { web.reload(); checkConnection(); } }); AlertDialog alertDialog = builder.create(); alertDialog.show(); } else { Toasty.info(VTOP.this, "Just a second", Toasty.LENGTH_SHORT).show(); web.setVisibility(View.VISIBLE); web.loadUrl("https://vtop.vitap.ac.in/vtop/login?logout/"); } }
额外注意事项
- 确保你的App已经在
AndroidManifest.xml中申请了INTERNET权限 - 如果测试后还是有问题,可以尝试清除WebView的缓存和Cookie,然后重新验证一次,看是否能持久化状态
- 有些网站的reCAPTCHA会基于设备指纹验证,上面的配置已经尽可能缩小WebView和Chrome的差异,一般能解决重复验证的问题
内容的提问来源于stack exchange,提问作者sai gopal
相关产品推荐
相关产品推荐

