Android WebView 中网页被劫持的原因及解决方案
文章目录
- 一、原因分析
- 二、解决方案一览
- 三、解决方案代码案例
- 3.1 使用 HTTPS
- 3.2 验证 URL
- 3.3 禁用 JavaScript
- 3.4 使用安全的 WebView 设置
- 3.5 监控网络请求
- 3.6 使用安全的 DNS
- 四、案例深入分析
- 4.1 问题
- 4.2 分析
- 五、结论
在 Android 应用开发中,WebView 是一个常用的组件,用于在应用内显示网页内容。然而,有时用户可能会发现网页被劫持到另一个不安全的网页。这种情况不仅影响用户体验,还可能带来安全隐患。本文将探讨导致网页被劫持的可能原因,并提供相应的解决方案。
一、原因分析
-
JavaScript 重定向
某个网页中包含以下 JavaScript 代码:window.location.href = "http://malicious-site.com";
这段代码会在页面加载时将用户重定向到恶意网站。
-
恶意网页
用户点击了一个链接,访问了一个看似正常的网站,但该网站实际上是一个钓鱼网站,包含重定向代码,试图引导用户输入敏感信息。
-
WebView 设置不当
开发者在 WebView 中未设置
WebViewClient
,导致 WebView 默认行为是打开所有链接,而不是在应用内处理。这可能导致用户被重定向到外部浏览器,增加了被恶意网站劫持的风险。 -
拦截 URL 加载
在
shouldOverrideUrlLoading
方法中,开发者没有正确处理 URL,例如:@Override public boolean shouldOverrideUrlLoading(WebView view, String url) {// 没有验证 URL,直接加载view.loadUrl(url);return true; }
这可能导致用户被重定向到不安全的网站。
-
广告或跟踪脚本
某些网页可能嵌入了广告或跟踪脚本,这些脚本会在用户访问时自动重定向到广告商的网站,甚至可能是恶意网站。
-
中间人攻击
在公共 Wi-Fi 网络中,攻击者可能通过中间人攻击拦截用户的网络请求,并将其重定向到恶意网站,伪装成合法网站。
-
DNS 劫持
用户的 DNS 请求被劫持,导致访问某个合法网站时,实际上被重定向到攻击者控制的 IP 地址。例如,用户输入
www.example.com
,但由于 DNS 劫持,实际访问的是malicious-site.com
。
二、解决方案一览
为了减少网页被劫持的风险,开发者可以采取以下措施:
-
使用 HTTPS:确保访问的网页使用 HTTPS,这样可以减少中间人攻击的风险。
-
验证 URL:在
shouldOverrideUrlLoading
方法中,验证即将加载的 URL,确保它是安全的。 -
禁用 JavaScript:如果不需要 JavaScript,可以考虑禁用它,减少潜在的重定向风险。
-
使用安全的 WebView 设置:确保 WebView 的设置是安全的,例如启用安全的内容加载策略。
-
监控网络请求:使用网络监控工具,查看 WebView 中的网络请求,识别潜在的恶意重定向。
-
使用安全的 DNS:考虑使用安全的 DNS 服务(如 DNS over HTTPS),以减少 DNS 劫持的风险。
三、解决方案代码案例
以下是针对解决方案中提到的每个措施的代码案例,以帮助开发者更好地理解如何在 Android WebView 中实现这些安全措施。
3.1 使用 HTTPS
确保加载的网页使用 HTTPS。可以在加载 URL 前进行检查:
private void loadUrl(WebView webView, String url) {if (url.startsWith("https://")) {webView.loadUrl(url);} else {// 提示用户或处理不安全的 URLToast.makeText(context, "不安全的链接,无法加载!", Toast.LENGTH_SHORT).show();}
}
3.2 验证 URL
在 shouldOverrideUrlLoading
方法中验证即将加载的 URL:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {if (isSafeUrl(url)) {view.loadUrl(url);} else {// 提示用户或处理不安全的 URLToast.makeText(context, "不安全的链接,无法加载!", Toast.LENGTH_SHORT).show();}return true;
}private boolean isSafeUrl(String url) {// 这里可以添加更复杂的 URL 验证逻辑return url.startsWith("https://") || url.startsWith("http://trusted-site.com");
}
3.3 禁用 JavaScript
如果不需要 JavaScript,可以在 WebView 设置中禁用它:
WebView webView = findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(false); // 禁用 JavaScript
3.4 使用安全的 WebView 设置
确保 WebView 的设置是安全的,例如启用安全的内容加载策略:
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW); // 禁止混合内容
webSettings.setDomStorageEnabled(true); // 启用 DOM 存储
3.5 监控网络请求
使用 WebViewClient
监控网络请求,识别潜在的恶意重定向:
webView.setWebViewClient(new WebViewClient() {@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);// 监控页面加载Log.d("WebView", "Loading URL: " + url);}@Overridepublic void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {super.onReceivedError(view, request, error);// 处理加载错误Toast.makeText(context, "加载错误: " + error.getDescription(), Toast.LENGTH_SHORT).show();}
});
3.6 使用安全的 DNS
在 Java 层,DNS 解析由 AddressCache
管理。当未命中缓存时,会调用 Libcore.os.android_getaddrinfo
方法进行域名解析。通过阅读源码发现,解析逻辑由 libc.so
中的 getaddrinfo
方法实现,而 WebView 中的域名解析逻辑也是通过 libwebviewchromium.so
调用这个底层方法。
为了优化 DNS 解析,我们可以使用 inline hook 的方式(具体方案可以参考 ShadowHook)来 hook getaddrinfo
方法。这样可以先查询我们维护的缓存,再进行相应的优化和兜底处理。
以下是一个简单的示例,展示如何使用 ShadowHook 来 hook getaddrinfo
方法:
import com.github.shadowhook.ShadowHook;public class DnsHook {public static void hookGetAddrInfo() {ShadowHook.hook("libc.so", "getaddrinfo", new ShadowHook.HookCallback() {@Overridepublic Object invoke(Object... args) {String hostname = (String) args[0];// 查询自定义缓存String cachedIp = queryCustomDnsCache(hostname);if (cachedIp != null) {// 返回缓存的 IP 地址return cachedIp;}// 调用原始的 getaddrinfo 方法return ShadowHook.callOriginal(args);}});}private static String queryCustomDnsCache(String hostname) {// 实现自定义 DNS 缓存查询逻辑return null; // 返回 null 表示未命中缓存}
}
四、案例深入分析
4.1 问题
用户点击链接A,会跳转到不良网站链接B。这个问题在用户手机上必现。
4.2 分析
-
因为用户在任何网络环境都能复现,怀疑是用户android端的系统DNS解析被劫持了。
验证方法:android端打开华佗诊断的DNS检测页面,发现解析结果为空。在其他浏览器打开链接A,也不会调整到链接B。说明系统的DNS解析没有被劫持。
检测页面链接:https://itango.tencent.com/app/data/huatuo
-
通过抓包工具分析,发现没有A域名的请求包。虽然界面上打开的是链接A,但是实际上Webview直接发起了B的请求。
通过这一点,怀疑是Webview缓存了之前在某个网络环境下的DNS解析结果,默认跳转到了链接B。
其中抓包工具使用的是:Reqable
下载链接是:https://reqable.com/zh-CN/android/
-
删除应用的【缓存】(不需要清除数据),用户恢复正常。验证了确实是Webview在应用沙箱中缓存了解析结果。
五、结论
在 Android WebView 中,网页被劫持的情况可能由多种因素引起,包括 JavaScript 重定向、恶意网页、设置不当等。通过采取适当的安全措施,开发者可以有效降低这些风险,保护用户的浏览体验和数据安全。确保在开发过程中关注这些潜在的安全隐患,将有助于提升应用的整体安全性和用户信任度。
相关文章:

Android WebView 中网页被劫持的原因及解决方案
文章目录 一、原因分析二、解决方案一览三、解决方案代码案例3.1 使用 HTTPS3.2 验证 URL3.3 禁用 JavaScript3.4 使用安全的 WebView 设置3.5 监控网络请求3.6 使用安全的 DNS 四、案例深入分析4.1 问题4.2 分析 五、结论 在 Android 应用开发中,WebView 是一个常用…...
特朗普政府将开展新网络攻击
近日,特朗普政府已表态:减少物理战争,网络战将代替,以实现美国的全球优势。 特朗普也指示美国网络司令部可以在没有总统批准的情况下开展更广泛行动,尤其是应对一些突发事件,这其实成为了后续美国通过网络…...

快递代取项目Uniapp+若依后端管理
快递接单代取得uniappspringboot项目 实际效果图...

arcgis短整型变为长整型的处理方式
1.用QGIS的重构字段工具进行修改,亲测比arcgis的更改字段工具有用 2.更换低版本的arcgis10.2.2,亲测10.5和10.6都有这个毛病,虽然官方文档里面说的是10.6.1及以上 Arcgis10.2.2百度链接:https://pan.baidu.com/s/1HYTwgnBJsBug…...

06、Redis相关概念:缓存击穿、雪崩、穿透、预热、降级、一致性等
Redis相关概念:缓存击穿、雪崩、穿透、预热、降级、一致性等 Redis缓存雪崩、缓存击穿、缓存预热热点key、缓存降级、短链接、分布式锁秒杀、预减库存、 堆外缓存Redis架构设计、Redis动态刷新、Redis和DB双写一致性、过期删除策略、集群数据倾斜等一、缓存雪崩 缓…...
嵌入式基础 -- PCIe 控制器中断管理之MSI与MSI-X简介
PCIe 控制器中断管理技术文档 1. 背景 在现代计算机系统中,中断是设备与 CPU 通信的重要机制,PCIe 控制器提供了从传统线中断到基于消息的中断(MSI/MSI-X)的演进,以提升中断处理效率和可扩展性。x86 和 ARM 架构虽然…...

websocket实现
由于安卓资源管理器展示的路径不尽相同,各种软件保存文件的位置也不一定一样.对于普通用户上传文件时,查找文件可能是一个麻烦的事情.后来想到了一个办法,使用pc端进行辅助上传. 文章目录 实现思路1.0 实现定义web与客户端通信数据类型和数据格式web端websocket实现web端对客户…...

unity学习20:time相关基础 Time.time 和 Time.deltaTime
目录 1 unity里的几种基本时间 1.1 time 相关测试脚本 1.2 游戏开始到现在所用的时间 Time.time 1.3 时间缩放值 Time.timeScale 1.4 固定时间间隔 Time.fixedDeltaTime 1.5 两次响应时间之间的间隔:Time.deltaTime 1.6 对应测试代码 1.7 需要关注的2个基本…...

【C++】特殊类设计、单例模式与类型转换
目录 一、设计一个类不能被拷贝 (一)C98 (二)C11 二、设计一个类只能在堆上创建对象 (一)将构造函数私有化,对外提供接口 (二)将析构函数私有化 三、设计一个类只…...

scratch七彩六边形 2024年12月scratch三级真题 中国电子学会 图形化编程 scratch三级真题和答案解析
目录 scratch七彩六边形 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、…...

代码随想录刷题day16|(哈希表篇)349.两个数组的交集
目录 一、哈希表理论基础 二、集合set在哈希法中的应用 三、相关算法题目 四、相关知识点 1.set集合特点和常用方法 1.1 set集合概述 1.2 set集合特点 1.3 常用方法 2.set集合转换成数组 法1:另新建一个数组 法2:将结果集合转为数组 ▲ 3.数组…...

Synology 群辉NAS安装(6)安装mssql
Synology 群辉NAS安装(6)安装mssql 写在前面mssql 2019:成功安装说明,这个最终成功了 mssql 2022没有成功1. pull image2.启动mssql docker container 远程连接 写在前面 mssq是一个重要节点。 这是因为我对mysql没有一丝好感。虽然接触了许…...

2025年美赛B题-结合Logistic阻滞增长模型和SIR传染病模型研究旅游可持续性-成品论文
模型设计思路与创新点: 建模的时候应该先确定我们需要建立什么类的模型?优化类还是统计类?这个题需要大量的数据分析,因此我们可以建立一个统计学模型。 统计学建模思路:观察规律,建立模型,参…...

Hook 函数
什么是hook函数? 在计算机编程中,hook函数是指在特定的事件发生时被调用的函数,用于在事件发生前或后进行一些特定的操作。通常,hook函数作为回调函数被注册到事件处理器中,当事件发生时,事件处理器会自动…...

蓝桥杯模拟算法:蛇形方阵
P5731 【深基5.习6】蛇形方阵 - 洛谷 | 计算机科学教育新生态 我们只要定义两个方向向量数组,这种问题就可以迎刃而解了 比如我们是4的话,我们从左向右开始存,1,2,3,4 到5的时候y就大于4了就是越界了&…...

DeepSeek-R1解读:纯强化学习,模型推理能力提升的新范式?
DeepSeek-R1解读:纯强化学习,模型推理能力提升的新范式? 1. Impressive Points2. 纯强化学习,LLM推理能力提升新范式?2.1 DeepSeek-R1-Zero2.2 DeepSeek-R1 3. 端侧模型能力提升:蒸馏>强化学习 1. Impre…...

深度解析:基于Vue 3的教育管理系统架构设计与优化实践
一、项目架构分析 1. 技术栈全景 项目采用 Vue 3 TypeScript Tailwind CSS 技术组合,体现了现代前端开发的三大趋势: 响应式编程:通过Vue 3的Composition API实现细粒度响应 类型安全:约60%的组件采用TypeScript编写 原子化…...

【PyTorch】3.张量类型转换
个人主页:Icomi 在深度学习蓬勃发展的当下,PyTorch 是不可或缺的工具。它作为强大的深度学习框架,为构建和训练神经网络提供了高效且灵活的平台。神经网络作为人工智能的核心技术,能够处理复杂的数据模式。通过 PyTorch࿰…...

Spring Boot整合JavaMail实现邮件发送
一. 发送邮件原理 发件人【设置授权码】 - SMTP协议【Simple Mail TransferProtocol - 是一种提供可靠且有效的电子邮件传输的协议】 - 收件人 二. 获取授权码 开通POP3/SMTP,获取授权码 授权码是QQ邮箱推出的,用于登录第三方客户端的专用密码。适用…...

字节跳动发布UI-TARS,超越GPT-4o和Claude,能接管电脑完成复杂任务
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...

DAY 45 超大力王爱学Python
来自超大力王的友情提示:在用tensordoard的时候一定一定要用绝对位置,例如:tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾: tensorboard的发展历史和原理tens…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...