背景
在iOS開(kāi)發(fā)的一些業(yè)務(wù)場(chǎng)景中,可能有一些敏感信息(如付款的二維碼等)冯键,我們不希望被隨意傳播惹盼。應(yīng)用內(nèi)禁止截屏,可以一定程度上惫确,提高敏感信息被傳播的門檻(可能需要另外一臺(tái)手機(jī)拍照手报,并手機(jī)間傳輸)。
然而改化,由于iOS系統(tǒng)的特殊性掩蛤,常規(guī)方法無(wú)法完全禁止用戶截屏落地成系統(tǒng)圖片。目前陈肛,網(wǎng)上的解決方案揍鸟,主要有兩種:
監(jiān)聽(tīng)截屏后通知(UIApplicationUserDidTakeScreenshotNotification),并進(jìn)行提示句旱。
讓用戶安裝禁用屏幕快照和屏幕錄制的配置文件阳藻。
前者無(wú)法禁止截屏內(nèi)容落地,后者閹割了手機(jī)功能前翎,導(dǎo)致其他應(yīng)用也無(wú)法截屏稚配。二者均不能滿足需求。
其他刪除本地相冊(cè)的方案在新系統(tǒng)上不能滿足需求港华。
本文在研究了參考資料給出的一些建議,使用DRM最終實(shí)現(xiàn)了對(duì)控件的防止截屏功能午衰。
該方案有以下特點(diǎn):
可以做到真正意義防止敏感內(nèi)容落地立宜。
沒(méi)有用到私有api冒萄,是蘋果原生支持的。
支持主流系統(tǒng)版本橙数。
注: 本文方案只能對(duì)敏感控件進(jìn)行防截屏處理尊流,無(wú)法做到全局任何位置防截屏(全部控件加drm,代價(jià)太大)灯帮。
使用DRM實(shí)現(xiàn)防止截屏
演示demo: https://github.com/ohswift/VTAntiScreenCapture
蘋果系統(tǒng)是支持DRM(Digital Rights Management崖技,數(shù)字版權(quán)管理)的。它表現(xiàn)在钟哥,當(dāng)你播放一個(gè)加密了的hls流時(shí)迎献,你進(jìn)行截屏(用手機(jī)截屏或用Xcode截屏),該視頻控件會(huì)顯示空白腻贰。
所以吁恍,我們的思路就很清晰了。我們可以把一個(gè)敏感信息的控件播演,轉(zhuǎn)化為帶DRM加密的視頻冀瓦,然后播放。此后写烤,系統(tǒng)進(jìn)行截屏?xí)r翼闽,該控件就會(huì)消失,達(dá)到防止敏感內(nèi)容落地的目的洲炊。
你可以在敏感信息控件后放個(gè)背景感局,用來(lái)在截屏?xí)r敏感控件消失后,做更友好的提示选浑。
如demo所示蓝厌。
演示工程的效果如下:
如demo所示,截屏截不到真實(shí)的內(nèi)容古徒,敏感信息會(huì)被過(guò)濾拓提。
我們的整個(gè)流程差不多如下:
根據(jù)控件內(nèi)容生成mp4文件
啟動(dòng)webserver
本地播放帶DRM加密的hls流
其中1不是重點(diǎn),我們將放后面講隧膘。我們先驗(yàn)證DRM是否真的可以做到防止截屏代态。假設(shè),我們已經(jīng)把一個(gè)文本內(nèi)容轉(zhuǎn)換為mp4了(demo工程中的text.mp4)疹吃。那么蹦疑,我們首先讓這個(gè)視頻可以播放起來(lái)。
啟動(dòng)webserver
我們需要把該mp4拷貝到一個(gè)目錄后萨驶,啟動(dòng)webServer歉摧,如demo中,我們把它拷到tmp目錄下(演示用,實(shí)際可以做到mp4數(shù)據(jù)也不落地)叁温。
[_webServer addGETHandlerForBasePath:@"/" directoryPath:dir indexFilename:nil cacheAge:3600 allowRangeRequests:YES];
[_webServer startWithPort:8989 bonjourName:nil];
播放帶hls加密的流
如果你按上面播放再悼,發(fā)現(xiàn)只是單純的展示內(nèi)容,并沒(méi)有防截屏的效果膝但。我們需要加密播放流冲九。
你可能需要一些AVPlayer播放視頻的基礎(chǔ),可以參考[iOS]仿微博視頻邊下邊播之封裝播放器和Playing Offline HLS with AES-128 encryption iOS跟束。
當(dāng)你理解了AVAssetResourceLoaderDelegate了后莺奸,就可以開(kāi)始了。我們讓播放器去播放一個(gè)私有協(xié)議的m3u8文件冀宴。
[self.player playURL:@"jedi://text.m3u8" inView:self.labelContainer];
而當(dāng)它無(wú)法解析時(shí)灭贷,就需要走AVAssetResourceLoaderDelegate,我們?cè)谄渲谢ǘ欤祷貙懰赖膖ext.m3u8數(shù)據(jù)氧腰。
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:5
#EXT-X-TARGETDURATION:1
#EXT-X-KEY:METHOD=SAMPLE-AES,URI="jedi://text.key"
#EXTINF:0.067,
http://localhost:8989/text.mp4
#EXT-X-ENDLIST
m3u8中寫入了mp4的url地址,同時(shí)刨肃,也通過(guò)EXT-X-KEY來(lái)描述當(dāng)前的加密key古拴,說(shuō)明當(dāng)前的流是經(jīng)過(guò)加密的。
同樣真友,這里的key的獲取也是用的私有協(xié)議黄痪,同樣需要走AVAssetResourceLoaderDelegate。所以盔然,最終AVAssetResourceLoaderDelegate中的方法看起來(lái)如下:
這里桅打,我們返回的key是16字節(jié)純0的數(shù)據(jù),其實(shí)mp4文件并沒(méi)有加密愈案,只是讓系統(tǒng)以為加密了挺尾,好在截屏?xí)r進(jìn)行保護(hù)。
如果你看到此站绪,應(yīng)該已經(jīng)基本掌握了防止截屏的大致流程了遭铺。如果效果無(wú)法達(dá)到的話,可以隨時(shí)參照demo中的示例恢准。
編碼生成mp4
這里用AVAssetWriter和CVPixelBuffer即可生成mp4魂挂。這里參考了https://github.com/caferrara/img-to-video.git的代碼。
VTMP4Encoder中包含根據(jù)view生成mp4的邏輯馁筐,這里不展開(kāi)涂召,感興趣的可以查看代碼。
注:要注意敏沉,AVAssetWriter要設(shè)置shouldOptimizeForNetworkUse = YES果正,
讓它支持faststart,否則在m3u8中播放不了炎码。
生成的mp4可以在demo中試用,或在mac端啟nginx配置m3u8測(cè)試舱卡。
Prevent screen capture in an iOS app
Playing Offline HLS with AES-128 encryption iOS
[iOS]仿微博視頻邊下邊播之封裝播放器辅肾。
img-to-video