版权声明:
本公众号发布的所有文章,均属于原创,版权归本公众号所有。
未经允许,不得转载。
在我们开发一些对屏幕显示内容的安全性有要求的 App 的时候,如果后台有运行恶意的程序对这些敏感页面进行截图,就可能导致这些信息的泄露。
比较常见的场景,就是微信或者支付宝的付款二维码,如果有恶意程序此时进行截图并且发送出去,就可能导致用户经济上的损失。
那么本片文章就如何防止在某些页面内截图的问题,进行一个详尽的讨论。
首先需要明确,防止截屏的功能,一般而言都是对 App 内单个页面的,全局禁用也没什么,还可能不利于用户分享传播,通常我们只需要对敏感页面进行限制即可。
这些敏感信息,一方面来自程序根据用户信息,自动生成的,例如前面举例的付款二维码。另外一方面,来自用户的主动录入,例如用户自己输入的帐号、密码(有些为了怕用户输入错误,有提供显示密码的开关)。
所以我们就这两种思路来进行分别的讨论。
对于这种程序自动生成的信息,在开发者看来,只需要保证截屏,截取到的信息是脏数据即可。就是说截屏保存的数据,其实是已经失效或者过期的即可。
但是对于 Android 系统而言,截屏并没有提供对应的广播或者其它回调来监听它,我们只能通过其他的方式来解决它。
现在主流的一些思路:
在 Activity.onPause() 中,刷新数据。
利用 FileObserver 监听截屏目录中,截图文件的变化情况。
利用 ContentObserver 监听全部资源的变化。
这些思路都是依赖于对方使用的是系统自己提供的截图方式,可能并不能详尽的覆盖到。例如第一种方法,在 onPause() 中刷新数据,其实就是利用了设备在截屏的时候,为了让用户有感知,所以会有一个截图的动画效果来提示用户已经截图成功,在此处被截屏的 Activity 就会走到 onPause() 生命周期内。但是有一些软件的截图方式,是不会有此动画的,所以完全会导致监听不到而导致信息泄露。
不过这种思路,不是本文的重点,本文的重点主要是第二种方式,这里只是简单介绍一下,之后有时间再做一个详情的讲解。
对于用户主动录入的信息,一般而言,哪怕我们可以通过第一种方式去修改它,也会很麻烦,最直接的办法,是看能不能直接禁用掉截屏的功能。
实际上,Android 是提供了对应的 Api 的,使用起来也非常的简单,只需要拿到 window 对象,对其添加一个 FLAG_SECURE
的 flag 即可。
完整的代码如下:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
这里的 window 对象,可以是 Activity.getWindow()
获取的,也可以是 Dialog.getWindow()
获取的,获取 window 的方式很多,这里就不一一举例了。只是使用不同对象获取到的 Window 对象,禁用截屏的区域也不同。
大部分情况下都推荐使用这种方法,禁用掉系统截屏的功能,一劳永逸。
FLAG_SECURE 是 WindowManager.LayoutParams
的一个属性,从文档上就可以看出来,它标记当前 window 是安全的,不允许有一些非安全的操作,例如截屏功能。
虽然 FLAG_SECURE
是一个官方推荐的 Flag ,但是我们还是需要测试一下是否靠谱。
测试设备 :Letv X600 Android 6.0
首先使用 Android Monitor 进行截图。
发现是会截图失败的,如下图所示,提示截图失败。
然后再使用手机自带的截图快捷键试试,同样会提示截图失败。
现在来看,这个 Flag 基本上是靠谱。
之后查阅了一些资料,在一些设备上也有一些不同的表现,例如,在三星手机上测试,发现会输出一个图片文件,但是内容被像素化了,如下图所示。
从自测和资料上来看,FLAG_SECURE
基本上可以保证我们显示的内容的安全性。但是有一些情况下 ,FLAG_SECURE
依然会有一些截屏泄露的情况。
因为 FLAG_SECURE
是应用在 Window 对象上的,如果在 Activity 中有一些弹窗或者突出的UI元素,都是不受 Activity 的 Window 对象保护的。例如:在Activity 中弹出对话框,虽然 Activity 被设置为 FLAG_SECURE
,但是如果有一个 Dialog 弹窗,对于弹窗的内容,依然需要单独设置 FLAG_SECURE
。
这些会出现截屏泄露的地方包括:
AutoCompleteTextView
Spinner(下拉菜单或者对话框模式中)
PopupWindow
ShareActionProvider
Toast
这些只是一部分,可能还有其他的地方也会造成截屏泄露。
下面展示一个在 @CommonsWare 博客中找到的 gif 图,可以清晰表明在这些情况下,依然是可以截取到内容的,所以我们在有重要信息需要隐藏的时候,要特别注意这些场景下也别暴露重要信息。
可以看到,在一个被设置为 FLAG_SECURE 的页面中,有些设备上依然会截取出黑色的画面,而这些导致截屏泄露的点,依然是可以截取到图像的。
@CommonsWare 的博客地址:
https://commonsware.com/blog/2016/06/06/psa-flag-secure-window-leaks.html
其实通篇就是在介绍一个 FLAG_SECURE 这个 flag 来保护屏幕的安全,禁止程序进行截屏,但是引申出一些值得我们思考的问题。