You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android WebView实现多站点账号密码自动填充技术求助

实现多网站账号密码自动填充方案

兄弟,我懂你现在的困境——当前代码只能死磕Facebook的表单字段,要扩展到用户选定的任意网站确实得换个灵活点的思路。下面给你一套落地的实现方案,亲测好用:

1. 先搞个网站配置映射表

首先你得维护一个网站-账号密码-表单字段的对应关系,这样不同网站的填充规则才能区分开。我习惯用HashMap存,每个网站对应一个配置对象,包含用户名、密码、以及该网站对应的用户名/密码字段名:

// 先定义个内部类存网站的填充规则
private static class SiteAuthConfig {
    String username;
    String password;
    String usernameField; // 比如Facebook是"email",GitHub是"login"
    String passwordField; // 大部分网站是"password",有些小众站是"pass"
    // 构造方法
    public SiteAuthConfig(String username, String password, String usernameField, String passwordField) {
        this.username = username;
        this.password = password;
        this.usernameField = usernameField;
        this.passwordField = passwordField;
    }
}

// 初始化网站配置表,后续可以让用户动态添加
private HashMap<String, SiteAuthConfig> siteAuthMap = new HashMap<>();

// 在初始化的地方(比如Activity的onCreate)添加用户选定的网站
private void initSiteConfigs() {
    siteAuthMap.put("facebook.com", new SiteAuthConfig("user", "pass", "email", "pass"));
    siteAuthMap.put("github.com", new SiteAuthConfig("my_github_id", "github_123", "login", "password"));
    siteAuthMap.put("google.com", new SiteAuthConfig("my_gmail", "google_456", "identifier", "Passwd"));
    // 更多网站可以让用户自己添加,比如通过设置页面录入
}

2. 页面加载完成后自动匹配填充

修改你的onPageFinished方法,先从当前URL里提取域名,找到对应的配置,再动态生成JS代码填充表单。为了避免因为字段查找方式单一导致失败,我加了多种元素查找逻辑(getElementsByName、getElementById、querySelector):

@Override
public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
    progressBar.setVisibility(View.GONE);

    // 从URL里提取域名,比如"https://www.facebook.com/login"提取成"facebook.com"
    String domain = extractDomain(url);
    if (domain == null || !siteAuthMap.containsKey(domain)) {
        // 当前网站不在用户选定的列表里,直接跳过
        return;
    }

    SiteAuthConfig config = siteAuthMap.get(domain);
    // 动态生成填充用的JS代码,兼容多种字段查找方式
    String jsFillCode = String.format("javascript:(function(){" +
            "// 填充用户名,挨个试查找方式,找到就赋值" +
            "var usernameEl = document.getElementsByName('%s')[0] || document.getElementById('%s') || document.querySelector('[name=\"%s\"]');" +
            "if(usernameEl) usernameEl.value = '%s';" +
            "// 填充密码同理" +
            "var passwordEl = document.getElementsByName('%s')[0] || document.getElementById('%s') || document.querySelector('[name=\"%s\"]');" +
            "if(passwordEl) passwordEl.value = '%s';" +
            "})()",
            config.usernameField, config.usernameField, config.usernameField, config.username,
            config.passwordField, config.passwordField, config.passwordField, config.password);

    // 执行填充JS
    view.loadUrl(jsFillCode);
}

// 辅助方法:从URL中提取纯净域名
private String extractDomain(String url) {
    try {
        URI uri = new URI(url);
        String host = uri.getHost();
        if (host != null) {
            // 去掉前面的www.前缀,统一域名格式
            return host.startsWith("www.") ? host.substring(4) : host;
        }
    } catch (URISyntaxException e) {
        e.printStackTrace();
    }
    return null;
}

3. 处理动态加载的表单(可选)

有些网站的登录表单是点击按钮后才动态加载的,onPageFinished触发时元素还没生成。这时候可以加个延迟执行:

// 延迟1秒执行填充,给动态元素留加载时间,时间可以自己调
view.postDelayed(() -> view.loadUrl(jsFillCode), 1000);

几个要注意的点

  • 安全性:绝对不能明文存用户的账号密码!用Android自带的EncryptedSharedPreferences加密存储才靠谱。
  • 字段兼容性:如果不想让用户手动填字段名,你可以做个自动检测逻辑——遍历页面里的input元素,把type为email/text的当作用户名输入框,type为password的当作密码框。
  • WebView基础设置:别忘了开启JavaScript支持,不然JS代码跑不起来:
webView.getSettings().setJavaScriptEnabled(true);

内容的提问来源于stack exchange,提问作者user2847219

火山引擎 最新活动