马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1.APP开发安全
AndroidManifest设置安全
每个Android应用的根目次中都必须包罗一个AndroidManifest.xml文件。Manifest文件为Android体系提供有关应用的根本信息,体系必须得到这些信息才气运行恣意应用代码
别的,Manifest文件还可实验以下操纵:
- 为应用的Java软件包定名。软件包名称充当应用的唯一标识符
- 形貌应用的各个组件,包罗构成应用的Activity、服务、广播吸收器和内容提供步调。为实现每个组件的类定名并发布其功能。根据这些声明,Android体系可以相识这组件具体是什么,以及在什么条件下可以启动它们
- 确定将托管应用组件的进程
- 声明应用必须具备哪些权限才气访问API中受掩护的部门并与其他应用交互
- 声明其他应用与该应用组件交互所需具备的权限
- 列出Instrumentation类,这些类可在应用运行期间提供分析和其他信息。这些声明只会在应用处在开发和测试阶段时出现在清单文件中,在应用发布之前会被删除
- 声明应用所需的最低Android API级别
- 列出应用必须链接的库
我们所熟知的导出组件,是Android上最常见也是门槛最低的攻击入口,如Manifest中组件设置不当的话,就存在被恣意调用的大概。别的,在Manifest设置文件中,另有一些可被调试的步调、可被导出的应用数据以及与Scheme相干的设置开关,一旦开启就会存在一些风险
Manifest设置不当类风险与对策:
毛病或风险产生缘故原由结果办理方案步调可被恣意调试AndroidManifest.xml设置错误,android:debuggable=“true”,调试开关被打开APP可以被调试修改AndroidManifest.xml设置为android:debuggable=“false”允许步调数据备份AndroidManifest.xml中allowBackup=“true”,数据备份开关被打开步调数据恣意备份,应用数据可被导出修改AndroidManifest.xml设置为allowBackup=“false”,并使用得当的掩护级别(如android:protectionLevel=“signature”)验证调用泉源Activity组件袒露Activity组件的exported属性被设置为true,或未设置exported但IntentFilter不为空,activity被以为是导出的Activity组件可被外部访问,实验越权攻击在AndroidManifest.xml中明白设置Activity组件的exported属性为false,若需与其他APP共享或交互数据,则举行权限控制和参数校验Service组件袒露Service组件的exported属性被设置为true,或未设置exported但IntentFilter不为空,service被以为是导出的Service组件可被外部访问,实验越权攻击同上ContentProvider组件袒露ContentProvider的exported属性被设置为true,或Android API<=16时默认导出越权访问应用自己不想共享的数据同上BroadcastReceiver组件袒露BroadcastReceiver的exported属性被设置为true,或未设置exported但IntentFilter不为空,BroadcastReceiver被以为是导出的BroadcastReceiver可被外部恶意调用,导致数据走漏或越权访问同上Intent Scheme URLs
攻击在 AndroidManifest.xml设置 Scheme 协议之后,可以通过欣赏器打开对应的 Activity访问欣赏器构造intent 语法即可唤起App相应组件,导致拒绝服务乃至越权活动设置 category filter,添加android.intent.category.BROWSABLE方式规避风险Activity组件安全
在Android开发中,Activity 是四大组件之一(包罗 Activity、Service、BroadcastReceiver 和 ContentProvider),它负责用户界面和用户交互。由于 Activity 是用户直接交互的组件(用户唯一可以或许望见的组件),以是其安全性非常告急。
1、组件导出袒露标题
Activity 可以通过 AndroidManifest.xml 文件中的 android:exported 属性来控制是否允许其他应用调用。如果不渴望其他应用启动你的 Activity,应将 android:exported 属性设置为 false
2、访问权限控制
为了掩护 Activity 不被未经授权的应用访问,你可以使用 android:permission 属性来指定一个权限字符串,只有具有该权限的应用才气启动这个 Activity,比方:
- <activity
- android:name=".MySecureActivity"
- android:permission="com.example.MY_PERMISSION">
- </activity>
复制代码 在这个示例中,MySecureActivity 只有在其他应用声明并持有 com.example.MY_PERMISSION 权限时才可以启动。必要在 AndroidManifest.xml 文件中界说这个权限,如下所示:
- <manifest xmlns:android="http://schemas.android.com/apk/res/android">
- <permission
- android:name="com.example.MY_PERMISSION"
- android:protectionLevel="signature" />
-
- <application>
- <activity
- android:name=".MySecureActivity"
- android:permission="com.example.MY_PERMISSION">
- </activity>
- </application>
- </manifest>
复制代码 3、挟制标题
在启动Activity时,参加标记位FLAG_ACTIVITY_NEW_TASK,就能使该Activity置于栈顶立刻出现给用户。恶意软件可以监控 目的Activity,侦测到目的Activity启动后,立刻弹出一个与该应用界面雷同的 Activity,实现伪装目的Activity,也就是我们所说的“被挟制”标题
针对Activity挟制现在没有特殊好的办法彻底办理,一个思绪是在APP一些关键界面(比如登录界面)被覆盖时弹出一些提示信息,进入配景的时间判定是不是用户自己触发,如果不是也弹出提示信息。
Service组件安全
Service组件是Android体系中的配景进程,告急的功能是在配景举行一些耗时的操纵。
发起私有Service不界说intent-filter而且设置exported为false,必要被同公司差别APP访问时,可以将protectionLevel设置为signature;如果是相助搭档APP访问,必要对其APP署名做校验。若存在Service返回数据的环境,则必要关注敏感信息泄漏风险。
Provider组件安全
Content Provider组件是Android应用的告急组件之一,管理对数据的访问,告急用于差别的应用步调之间实现数据共享。Content Provider的数据源不止包罗SQLite数据库,还可以是文件数据。通过将数据储存层和应用层分离,Content Provider为各种数据源提供了一个通用的接口。
Content Provider组件允许其他应用通过 URI来访问应用的数据,如果在AndroidManifest文件中将某个ContentProvider的exported属性设置为true,就会产生一些越权访问数据、SQL注入、目次遍历等风险。比方:
1、私有权限界说错误导致数据被恣意访问
私有权限界说经常发生的风险是:界说了私有权限,但是根本没有界说私有权限的级别,大概界说的权限级别不敷,导致恶意应用只要声明这个权限就可以或许访问相应的Content Provider提供的数据,造成数据泄漏
2、当地SQL注入毛病
Content Provider的query()如果使用拼接字符串构成的SQL语句去查询底层的SQLite数据库时,轻易发生SQL注入
3、目次遍历毛病
对外袒露的Content Provider实现了OpenFile()接口。如果没有举行Content Provider访问权限控制和对访问的目的文件的URI举行有用判定,攻击者使用“../”实现目次遍历便可访问恣意可读文件。更有甚者,在Openfile()接口的实现中,如果要访问的文件不存在,就会创建此文件,也就是说另有大概往手机装备可写目次中写入恣意数据。
防御本事:
- 由于API level在17以下的全部应用的“android:exported”属性默认值都为true,因此如果应用的ContentProvider不必导出,发起显式设置注册的Content Provider组件的“android:exported”属性为false。
- 如果必须要有数据提供给外部应用,则必要做好权限控制,明白什么样的外部应用可以使用,只管不要提供用户隐私敏感信息。一样寻常来讲,大部门开放的Provider,都是提供给本公司其他应用使用,一样寻常打包署名APP的署名证书是划一的,如许便可以将Provider的ProtectionLevel设置为signature。如果是相助方的APP来访问,可以将相助方APP的署名哈希值预埋在提供Provider的APP中,提供Provider的APP要查抄哀求访问此Provider的APP的署名,匹配通过了才气访问
- 为了制止SQL语句,不要使用拼接字符串的情势,可以使用SQLiteDatabase类中的参数化查询query()方法。
- 为了防止目次遍历,发起去除Content Provider中的OpenFile()接口,对访问的目的文件路径举行有用判定,过滤“../”等字符串
BroadcastReceiver组件安全
BroadcastReceiver中文被译为广播吸收者,用于处理处罚吸收到的广播,广播吸收者的安全分为吸收安全与发送安全两个方面
1、吸收安全
动态注册广播如果仅为应用内部使用,应当将exported设置为false,如许外部应用不能恣意发送广播到自身步调中。如果必要吸收外部应用,则必要设置权限,和前面Provider的一样,如果是本公司其他APP,将ProtectionLevel设置为signature;如果是其他相助搭档的APP,则除了设置ProtectionLevel外还发起制止敏感信息的通报。
2、发送安全
Android体系提供了两种广播发送方法,即sendOrderedBroadcast和sendBroadcast。
有序广播通过Context.sendOrderedBroadcast()来发送,全部的广播吸收器优先级依次实验,广播吸收器的优先级通过receiver的intent-filter中的android:priority属性来设置,数值越大优先级越高。当广播吸收器吸收到广播后,可以使用setResult()函数来将效果传给下一个广播吸收器吸收,然后通过getResult()函数取得上个广播吸收器吸收返回的效果。当广播吸收器吸收到广播后,也可以用abortBroadcast()函数让体系拦截下该广播,并将该广播抛弃,使该广播不再传送到别的广播吸收器吸收。
平常广播是完全异步的,通过Context的sendBroadcast()方法来发送,消息通报服从比力高,但全部receivers(吸收器)的实验序次不确定。吸收器不能将处理处罚效果通报给下一个吸收器,而且无法制止广播 Intent的传播,直到没有与之匹配的广播吸收器为止。
Android官方在SDK文档中分析白一些不安全的API,包罗:sendStickyBroadcast、sendStickyOrderedBroadcast、sendStickyOrderedBroadcastAsUser、sendStickyBroadcastAsUser,发起不要在 APP使用。
WebView组件安全
WebView是一个基于Webkit引擎、显现Web页面的组件,APP通过调用该组件就可以访问网页内容,以是有非常多的移动应用都内嵌了WebView组件
对黑客而言,它是一个非常抱负的攻击面,点开一个链接大概扫描一个二维码就会实验恶意代码。在使用WebView组件过程中,除了一些体系隐蔽接口,还会有一些与当地交互、生存暗码、HTTPS通讯认证相干的风险必要关注,常见WebView风险如下表:
毛病或风险产生缘故原由结果办理方案<font style="color:#0e0e0e;">addJavascriptInterface</font>长途代码实验毛病Android 的 WebView 组件提供了一个 <font style="color:#0e0e0e;">addJavascriptInterface</font> 方法,用于实现当地 Java 代码和 JavaScript 代码之间的交互在targetSdkVersion 小于17时(Android 4.2),攻击者使用接口<font style="color:#0e0e0e;">addJavascriptInterface</font> 添加的函数,可以长途实验恣意代码
克制使用addJavascriptInterface,保举使用 <font style="color:#0e0e0e;">@JavascriptInterface</font> 注解来进步安全性Webview 组件体系隐蔽接口未移除毛病在 Android WebView 组件中,存在一些隐蔽的体系接口,如 <font style="color:#0e0e0e;">searchBoxJavaBridge_accessibility</font>, <font style="color:#0e0e0e;">Traversal</font>, 和 <font style="color:#0e0e0e;">accessibility</font>,这些接口在早期的 Android 版本中未被得当地限定,从而大概导致长途代码实验的安全风险使用 Android WebView 组件时,如果没有移除这3个导出接口,大概导致长途代码恣意实验使用 <font style="color:#0e0e0e;">WebView.removeJavascriptInterface(String name)</font> 方法显式地移除隐蔽体系接口通过 JavaScript 调用 getClassLoader 方法,实现长途代码实验在低于 API 17 的版本中,在 Context 子类中使用 <font style="color:#0e0e0e;">addJavascriptInterface</font> 方法将 this 对象(即当前 Context 对象)绑定到 WebView 上调用 getClassLoader,绕过 Google 对 getClass 方法的安全限定,从而实验恣意代码<font style="color:#0e0e0e;">targetSdkVersion</font>使用大于17的版本Webview暗码明文生存毛病WebView 大概会将用户输入的敏感信息(如用户名和暗码)明文生存在应用数据目次下的 <font style="color:#0e0e0e;">databases/webview.db</font> 文件中用户暗码信息泄漏风险可以使用 WebSettings 对象来设置 WebView 的设置。具体来说,你可以调用 <font style="color:#0e0e0e;">WebSettings.setSavePassword(false)</font> 来禁用暗码生存功能Webview启动访问文件数据导致用户隐私泄漏<font style="color:#0e0e0e;">setAllowFileAccess(true)</font> 允许 WebView 访问装备的文件体系,包罗应用的私有目次可以实验恣意 JavaScript 代码,并有大概绕过同源战略,进而访问私有目次中的文件。导致用户隐私泄漏或敏感数据被恶意使用通过调用 <font style="color:#0e0e0e;">WebView.getSettings().setAllowFileAccess(false) </font>克制 WebView 访问文件体系 2.APP业务安全
代码安全
Android体系的开源以及基于Java的特性,导致APP在Android上更轻易被反编译。现在常用的一些反编译工具(比如APKTool、dex2jar等)可以或许绝不费劲地还原Java里的明文信息,Native里的库信息也可以通过objdump或IDA获取。
而心怀不轨的人大概会通过反编译后参加恶意的代码逻辑,重新打包一个APK文件去发布安装,也就是我们常说的“二次打包”标题。针对这些标题,常见的办理方案是代码肴杂、加壳、反调试、署名验证等
1、代码肴杂
APP的代码肴杂包罗Java代码的肴杂以及一些资源文件的肴杂
ProGuard代码肴杂工具,开发职员可以使用它对自己的代码举行掩护。ProGuard提供了压缩、肴杂、优化代码以及反肴杂栈跟踪的功能
资源文件的肴杂,一些互联网公司也提供了一些方法供参考,比如微信提供的:
https://github.com/shwenzhang/AndResGuard
下载所在:https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/
2、加壳
Android加壳分为dex加壳和对native编译(即so文件加壳)主流的加壳技能根本可以分为四代:
1️⃣团体dex加壳
在开发过程中,classes.dex 文件会被加密。加密后的 dex 文件通常被存储在 APK 的资源文件中(如 assets 或 res 目次),而不是直接以明文情势包罗在 APK 中
当应用运行时,加载一个解壳代码或库,它会在内存中将加密的 dex 文件解密为原始的 classes.dex。此过程不会将解密后的文件直接写入磁盘,而是将解密后的代码存放在内存中
一旦 dex 文件在内存中解密,应用会使用 Dalvik 假造机(或 Android 5.0 之后的 ART 假造机)通过反射或 ClassLoader 动态加载解密后的代码,从而使应用继续运行
2️⃣防调试防Dump
团体dex在内存中解密,黑客通过内存Dump的方式即可拿到明文,以是出现了防调试、防内存Dump的技能
3️⃣方法体抽离
相比前面团体加壳加密,第三代开始实验只对classes.dex文件中的方法、函数举行抽取加密,在Java假造机实验具体某个方法时才将其动态解密,并以不连续的方式存放到内存中。反面逐步发展成将Java代码内关键算法、业务逻辑等函数主动转化成native的C++代码举行防护
4️⃣VMP加壳/so加壳
我们知道步调的实验,是依赖CPU对于符合规范的指令集的分析处理处罚。如果将原指令集通过自界说规范举行变形处理处罚,天生新的指令集(称之为假造指令集),CPU将无法辨认假造指令。此时若共同可以或许分析假造指令集的表明器(称之为假造机),就可以到达不直接通过CPU而是通过假造机来实验假造指令。这就是许多公司各种VMP掩护方案的根本原理
某厂商网站上的风险形貌表:
品级风险形貌人群分布发起或步调1使用apktool、dex2jar、jd-gui、baksmali等工具,直接检察Java代码99%对DEX文件加密,或将焦点代码封装到SO文件中2使用 DexExtractor 等主动脱壳工具,通过内存数据动态提取 Java 代码10%接纳Java2c技能,将Java代码转化为C代码,增长反编译难度,并举行SO加壳掩护3可修复ELF文件,并使用IDA工具反编译还原后的SO文件,分析焦点代码逻辑2%对SO文件举行代码肴杂加密掩护4可剔除 SO 文件中的肴杂代码,主动化还原原始代码0.5%对焦点代码举行假造化加密掩护5可分析自界说 CPU 指令,并主动化还原原始 CPU 指令0.001%定制升级假造化方案 APP加固的目的是提拔对手的攻击本钱,如果通过加固能让相称一部门人知难而退,就到达APP加固自己的效果了
在实际工作中,思量到APP内部复杂的业务场景和升级机制,有一些加固方案大概会存在肯定的兼容性标题,用户体验要求高的场景大概还会寻求运行速率,因此必要慎重权衡。一样寻常的思绪是在APP上举行各种埋点,联合后端大数据风控来低沉安全风险。
3、反调试
1️⃣使用android.os.Debug.isDebuggerConnected()这是最常见的 API,用于判定调试器是否已毗连到当进步程。如果返回 true,则表现应用正在被调试,可以根据这个信号采取防御步调或制止进程
2️⃣通过查抄 <font style="color:#0e0e0e;">ApplicationInfo.FLAG_DEBUGGABLE</font> 属性,可以判定应用是否是以 debug 模式运行。生产环境中的应用一样寻常不会开启此标记位,如果检测到 <font style="color:#0e0e0e;">FLAG_DEBUGGABLE</font> 为 true,可以视为潜伏的调试活动。
- boolean isDebuggable = (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
复制代码 3️⃣android_server 是一些调试工具(如 GDB、LLDB)使用的调试服务。如果发现该进程或相干端口正在监听,大概表现当进步程正在被调试。可以通过遍历 <font style="color:#0e0e0e;">/proc/net/tcp</font> 等体系文件查抄是否有调试端口开启
4️⃣TracePid 是 Linux 内核中的一个字段,当应用被调试时,该字段会表现调试器的 PID。可以通过循环读取 <font style="color:#0e0e0e;">/proc/self/status</font> 来判定是否被调试
- String status = readFile("/proc/self/status");
- if (status.contains("TracerPid:\t0")) {
- // 没有被调试
- } else {
- // 被调试
- }
复制代码 5️⃣检测模仿器。模仿器检测技能,一样寻常是取一些模仿器特性,比方通过电话管理器攻取装备IMEI、IMSI,判定装备设置信息与Android模仿器装备设置默认值是否雷同,检测装备是否有安装蓝牙装备硬件,判定当前装备WIFI MAC所在,检测是否具有QEMU假造机通道文件等。
6️⃣检测装备是否已经ROOT。ROOT检测一样寻常的思绪是,看ROOT后的手机会有哪些特性,比如,检测su文件是否存在及可以实验,检测是否安装<font style="color:#0e0e0e;">Superuser.apk</font>等。但实际环境是,Android碎片化非常严峻,国产手机厂商特殊喜欢修改原生ROM,这会导致一些检测方法失效,必要关注
4、署名验证
署名验证告急是为了防止二次打包,Android署名验证一样寻常有三种方法:
- Java层验证,即在Java代码中实现公钥信息的比对,比对的样本可以放在当地大概服务器侧。但是 Java代码轻易被反编译,这个校验逻辑大概被篡改
- NDK层验证,即在Native代码实现公钥信息的比对,比对的样本举行加密存储。我们知道so通过反汇编天生的ARM代码,相对smali被篡改的难度更大,再联合so文件加固,可以进一步增强反编译难度
- 服务端验证,即步调通过特定方法检测获取自身代码校验值,上送云端服务器举行比力,从而验证合法性。如许针对那些非法或伪造、篡改过的客户端,服务端可以直接拒绝服务,进一步保障安全
数据安全
针对APP,我们通常说的敏感信息包罗两方面:
一是用户敏感信息,比如用户名、暗码、手机号、邮箱、身份证、银行卡、住址等
二是APP自己的一些敏感信息,包罗产物核默算法、焦点业务逻辑、私钥、当地存储的证书、加密算法等
这些敏感信息都必要在计划APP时思量严格掩护,在存储、使用、传输过程中也要思量掩护方法
1、数据存储安全
Android有外部存储和内部存储之分,外部存储安全隐患比力大
1️⃣涉及用户隐私哪怕是已经加密过的也不要生存到外部存储装备上,另有一些APP会动态加载一些外部资源,这些外部资源大概生存在外部存储上,发起在加载时验证文件完备性。在做代码审计的时间,关注getExternalStorageState、getExternalStorageDirectory等关键函数就能定位到APP使用外部存储的代码逻辑
2️⃣内部存储是全部软件存放私有数据的地方,Android SDK中提供了openFileInput() 与openFileOutput() 方法来读写步调的私有数据目次。openFileOutput() 方法的第二个参数指定了文件创建模式,如果使用了MODE_WORLD_READABLE 或 MODE_WORLD_WRITEABLE,就大概导致敏感信息泄漏
3️⃣除了File方式外,Android还提供了Shared Preference、SQLite、ContentProvider方式举行数据存储。与openFileOutput()方法一样,Shared Preference的getSharedPreferences方法打开文件时第二个参数如果设置为MODE_WORLD_READABLE或MODE_WORLD_WRITEABLE都存在一样的标题,应将第二个参数设置为MODE_PRIVATE,如许就可以使用Linux的文件权限机制来确保数据不被其他进程访问
单单依赖MODE_PRIVATE模式是不敷的,由于大概APP运行在一个已经被Root的手机上,大概手机体系出现了一些毛病导致进程可以提拔权限,以是每每敏感数据会采取加密步调
Android SDK提供了一些API供加密使用,这些API和JAVA提供的根本相似,由Java Cryptography Architecture(JCA,Java加密体系布局)、Java Cryptography Extension(JCE,Java加密扩展包)、Java Secure Sockets Extension(JSSE,Java安全套接字扩展包)、Java Authentication andAuthentication Service(JAAS,Java辨别与安全服务)构成
- JCA提供根本的加密框架,如证书、数字署名、消息择要和密钥对产生器等
- JCE扩展了JCA,提供了各种加密算法、择要算法、密钥管理等功能
- JSSE提供了基于SSL(安全套接层)的加密功能,供HTTPS加密传输使用
- JAAS提供了在Java平台上举行用户身份辨别的功能
除别的,Android还提供了android.security和android.security.keystore来管理keychain和keystore。(Keychain 是用于管理用户证书和私钥的体系级存储机制,允许应用步调通过体系安全接口访问这些根据;Keystore 是 Android 提供的加密密钥管理体系,允许应用安全地天生、存储和使用加密密钥)
如果使用SQLite数据库的时间必要加密,可以使用SQLCipher方案。SQLCipher是个独立的SQLite数据库实现,但它并没有自己实现一套加密算法,而是使用了OpenSSL的libcrypto库,兼容性更好
4️⃣关于加密算法的选择和使用:
- base64只是一种编码方式,并不是加密算法
- 天生随机数时,不要使用Random类,使用SecureRandom类的时间,不要调用setSeed方法,即不要设置种子
- 使用HASH算法时,不要使用MD2、MD4、MD5、SHA-1、RIPEMD算法来加密用户暗码等敏感信息,由于网上有大量的库可以用来破解,发起使用SHA-256、SHA-3算法
- 使用消息认证算法时,发起使用HMAC-SHA256算法,制止使用CBC-MAC
- 使用对称加密算法时,不发起使用DES,发起使用AES算法,同时必要注意加密模式要显式指定为CBC或CFB模式,不要使用默认的ECB模式
- 非对称算法使用RSA时,发起密钥长度不低于512,同时注意重放攻击
- 使用基于口令的加密算法PBE时,天生密钥时要加盐,盐的取值最好来自SecureRandom,并指定迭代次数
- 白盒加密技能的焦点头脑是将加密算法和密钥打包成一个不可分割的团体,并天生加密表息争密表。加密息争密操纵不再依赖传统的算法实验,而是通过查表的方式完成。这种方式使得纵然攻击者可以或许获取到加密或解密过程,也无法直接从中提取出密钥或还原算法
2、数据传输安全
一样寻常客户端使用HTTPS与服务端举行通讯,网站启用SSL site wide(use HTTPS only)或HSTS(HTTP Strict Transport Security),否则存在SSL Strip(HTTPS降级为HTTP)攻击风险
3.其他
安全输入键盘
金融行业APP,暗码每每涉及款子,为了确保输入安全,一些企业会自行开发安全输入键盘
如许当用户输入暗码的时间,处于自行开发的暗码键盘掩护之下,确保用户暗码安全。固然除了暗码,另有其他的输入数据也必要掩护,比方用户的身份证号等敏感数据
防截屏
在 Android 体系中,由于没有直接提供对截屏变乱的监听接口或广播,开发者必要依赖间接的检测机制来应对截屏活动,当发现有截屏时做一些处理处罚,比如用纯玄色图片对象举行覆盖处理处罚。
1、使用 FileObserver 监听目次变革
FileObserver 是 Android 提供的一个用于监控 文件体系变革的类,可以监听文件或目次的创建、删除、修改等操纵。通过监控 体系默认的截图生存目次(如 /Pictures/Screenshots),可以检测到截屏操纵
比方:
- FileObserver screenshotObserver = new FileObserver(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES + "/Screenshots").getPath()) {
- @Override
- public void onEvent(int event, String file) {
- if (event == FileObserver.CREATE) {
- // 截屏事件检测到
- handleScreenshot();
- }
- }
- };
- screenshotObserver.startWatching();
复制代码 2、使用 ContentObserver 监听全局资源变革
ContentObserver 用于监听内容提供者中的数据变革。通过监听体系媒体数据库中的资源变革(如媒体库),可以检测到截图文件的新增
比方:
- ContentObserver mediaObserver = new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- // 检查媒体库中是否有新的截屏文件
- handleScreenshot();
- }
- };
- getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, mediaObserver);
复制代码 3、使用 <u><font style="color:#0e0e0e;">Activity.onPause() </font></u>机制
<font style="color:#0e0e0e;">onPause()</font> 方法在 Activity 失去焦点时调用。在某些环境下,如果用户截屏时应用失去焦点,可以在 <font style="color:#0e0e0e;">onPause()</font> 中举行检测或采取掩护步调
例子:
- @Override
- protected void onPause() {
- super.onPause();
- // 当 Activity 失去焦点时,尝试检测是否存在截屏
- handleScreenshot();
- }
复制代码 4、使用 View 层面的掩护步调
在应用的 View 层面,尤其是在敏感数据的界面,可以通过设置 <font style="color:#0e0e0e;">FLAG_SECURE</font> 来防止内容被截图。这会制止体系截屏和其他屏幕录制工具捕获该 Activity 的内容
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
复制代码 |