请教一个同源策略的问题

2025 年 9 月 1 日
 elinktek

需要 android 程序自动注入 js 表单信息,用户名密码,然后提交 网址是: https://aa.bb.buzz/test 实际网页的源码是 https://aa.bb.buzz/test/frame.html 我写的是 webView.loadUrl("https://aa.bb.buzz/test/frame.html"); 现在要求必须写成 webView.loadUrl("https://aa.bb.buzz/test");我查了 AI 说不能直接操作这个网址

AI 的解释: 为什么会失败? 同源策略 (Same-Origin Policy):

一个网页的“源”由协议、域名和端口号共同决定。

父页面 URL: https://aaa.buzz/test/,其源是 https://aaa.buzz

iframe URL: https://test01.aaa.buzz/test/frame.html ,其源是 https://test01.aaa.buzz

尽管这两个域名都属于 aaa.buzz ,但 test01.aaa.buzz 是一个不同的子域名,因此根据同源策略,它们被视为不同的源。

出于安全考虑,浏览器严格禁止一个源的脚本(例如注入到父页面的 JavaScript )访问另一个源的 DOM 内容(例如 iframe 里的表单元素)。这正是您日志中显示的 SecurityError 错误的原因。

shouldOverrideUrlLoading 的局限性:

您尝试使用 shouldOverrideUrlLoading 方法来拦截 iframe 的加载,但这通常只适用于主页面的导航事件(如用户点击链接或重定向)。WebView 加载 <iframe> 内部内容的行为,通常不会触发这个回调。因此,您的代码无法在 iframe 加载时进行拦截并跳转。

目前写的关键代码:

public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private static final String TAG = "WebViewApp";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webView);

        // 启用 JavaScript
        webView.getSettings().setJavaScriptEnabled(true);

        // 绑定 JavaScript 接口
        webView.addJavascriptInterface(new WebAppInterface(this), "Android");

        // 设置 WebViewClient ,监听页面加载完成
        webView.setWebViewClient(new MyWebViewClient());

        // 直接加载包含表单的 URL
        webView.loadUrl("https://test01.aaa.buzz/test/frame.html");
    }

    private class MyWebViewClient extends WebViewClient {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            Log.d(TAG, "Page finished loading: " + url);

            // 注入一个健壮的 JavaScript 代码,使用更通用的方法查找元素,并将代码压缩为单行
            String js = "(function() { function waitForElementsAndSubmit() { var inputs = document.getElementsByTagName('input'); var buttons = document.getElementsByTagName('button'); var usernameInput = null; var emailInput = null; var submitButton = null; var inputCount = 0; for (var i = 0; i < inputs.length; i++) { if (inputs[i].type === 'text') { if (!usernameInput) { usernameInput = inputs[i]; } else { emailInput = inputs[i]; break; } } } for (var i = 0; i < buttons.length; i++) { if (buttons[i].type === 'submit' || buttons[i].id === 'submit') { submitButton = buttons[i]; break; } } if (usernameInput && emailInput && submitButton) { console.log('找到所有元素,开始填写和提交。'); usernameInput.value = 'test'; emailInput.value = 'test@qq.com'; var form = submitButton.closest('form'); if (form) { form.submit(); } else { submitButton.click(); } setTimeout(function() { Android.showToast('表单已自动提交。'); }, 1000); } else { console.log('未找到元素,继续等待...'); setTimeout(waitForElementsAndSubmit, 200); } } waitForElementsAndSubmit(); })();";

            view.evaluateJavascript(js, null);
        }
    }

    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }
}

求大神指点,谢谢

1843 次点击
所在节点    程序员
6 条回复
shadowyue
2025 年 9 月 1 日
没看懂,怎么突然冒出来个 test01
okakuyang
2025 年 9 月 1 日
AI 的回答看不出与你的问题有啥联系。 不过因为同源问题拿不到 iframe 的内容可以理解
rabbbit
2025 年 9 月 1 日
没懂,不过 iframe 交互可以试试 postMessage
chenluo0429
2025 年 9 月 1 日
从你的代码里面没看到 iframe 啊,网页就是在 webview 中加载的,哪来的同源
elinktek
2025 年 9 月 1 日
页面的源碼是這個
```HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home Page</title>
</head>
<body>
<iframe name="test_frame" title="这是一个用于测试的内嵌页面" src="https://test01.aaa.buzz/test/frame.html" frameborder="0" style="width: 100%; height: 100%;"></iframe>
</body>
</html>

```
elinktek
2025 年 9 月 3 日
原来问题解决了。现在有新问题
问一下有人适配过小米手机吗?,这个 demo 用真机 android11 和 android16 ,虚拟机 android15 都测试正常,对方说小米的 android15 提交没有弹窗,我问 AI 小米是有一些特殊限制,我手边没有小米手机,谁有遇到类似的问题吗?

以下是 AI 回答:
```JAVA
小米的系统( MIUI )确实有一些特殊的系统设定,可能会导致你的应用行为与其他原生 Android 设备或虚拟机有所不同,尤其是在涉及 WebView 和后台任务时。

你遇到的问题很可能与以下几个方面有关:

1. MIUI 的进程和内存管理
MIUI 的后台进程清理非常激进。它可能会在应用进入后台或屏幕关闭时,更早地杀死进程或暂停 WebView 的活动,从而影响 setTimeout 或其他异步任务的执行。如果用户在表单自动提交完成前切换到其他应用,MIUI 可能直接中止了 WebView 的 JavaScript 引擎。

2. WebView 行为差异
虽然 Android 15 虚拟机和真机都基于相同的 Chromium 内核,但一些 OEM 可能会对 WebView 的底层行为进行微调,例如渲染时机、资源加载优先级或安全策略。

加载时机:onPageFinished 回调在某些设备上可能比在其他设备上更早触发。对于你的网页,主页面( https://sophiadesign.buzz/test/)的 onPageFinished 可能会在 iframe 中的内容完全加载完成之前就被调用。如果你的 JavaScript 注入得太早,它可能找不到 iframe 中的元素。

安全策略: 小米可能会对 JavaScript 在 WebView 中的行为有更严格的沙盒或安全限制,特别是当它尝试操作来自不同域的 iframe 内容时。

针对小米设备问题的解决方案
你之前使用的代码注入逻辑,虽然在大多数设备上有效,但可能存在一个**“竞态条件”( race condition )**。也就是说,JavaScript 注入和 iframe 内容加载完成之间存在时间差。

最稳妥的解决办法是直接加载表单页面,而不是通过父页面和 iframe 。
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1156378

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX