自從去年Google扶正了Kotlin,使之成爲了Android官方的推薦開發語言,Kotlin便迎來了春天。不少團隊/產品也紛紛加入了Kotlin的支持,大廠的應用也不少,社區對Kotlin也是讚不絕口。正在看此文的同窗,也相信要麼用上Kotlin,要麼準備使用Kotlin。html
這裏,筆者要給你們提個醒:舊項目引入Kotlin,如配置不當,會致使源碼泄露!。這意味着咱們所作的混淆、加固之類的防禦操做都白費了!這但是至關嚴重的安全問題!java
如圖。這是筆者在網上閒逛的時候,偶然發現的某應用包內居然包含了Kotlin的源文件!android
妥妥的如假包換的源文件,代碼、註釋都是全套的。編程
當筆者發現這個狀況的時候,心裏暗喜:難道筆者不當心挖到了一個Kotlin的大新聞,只要使用了Kotlin,就會被開源?安全
筆者嘗試在本地復現這個場景,但遺憾的是,不論是新版本的Kotlin Plugin仍是舊版本的Kotlin Plugin,打出來的包都不包含.kt
文件。隨後筆者又嘗試去應用寶抓取Top50的應用,發現使用了Kotlin的應用雖然多,但也沒出現圖上的應用通常的代碼泄露狀況。沒法復現,還怎麼定位問題的緣由?此時陷入了僵局。bash
後來,筆者查看自家的應用時,發現自家應用引入了Kotlin後,也出現了這樣的問題。那這就不是小事了。編程語言
排查和定位過程按下不表,直觀的結果就是,打出來的APK包裏,混入了源代碼目錄下的.kt
源文件。ide
咱們知道,打包過程當中,有一個步驟叫作Jar包資源合併,這個步驟會把Jar包內資源合併到一塊兒,打包到apk中。既然APK裏包含的.kt
文件,那極有多是合併資源的任務出了問題。工具
惋惜,比對了有問題的項目和正常的項目的build.gradle
以後,無奈的發現,即使是一樣的Gradle
、Kotlin Plugin
、build tools
版本,一樣的配置,依然沒法在正常的項目下復現這個問題。佈局
也就說,gradle
的Jar包資源合併任務並非致使問題的元兇。也是,Gradle若是有問題,社區也早就發現了。
但問題仍是得解決,既然是資源被合併打包了,那就找方法作指定資源的排除唄。
這部分的工做是由java plugin
乾的,那就到文檔: The Java Plugin
裏找答案。
首先看到這個任務:
從描述可知,這個任務就是咱們要找的,拷貝資源到jar包的資源目錄。
再往下看,項目的默認目錄結構:
資源目錄是放置在src/main/resources
,或對應的src/<代碼集>/resources
目錄內。
若是要自定義資源目錄的配置,看這個:
也就是說,這個配置指定了代碼集的資源目錄的位置。它會排除掉目錄內的.java
文件,其餘的插件,也可能從這裏移除掉額外的文件類型。
看到這裏,你們也差很少明白了吧?
講道理,默認生成的項目的目錄結構中,資源目錄和代碼目錄是區分開的。既然APK裏包含了.kt
源代碼,那必然是資源目錄和代碼目錄是同一個的狀況。
因爲java plugin
默認會移除資源目錄內的.java
文件,所以,在以往的打包中,源代碼可以被安全的移除掉,不至於致使泄露。
而如今,咱們引入Kotlin的時候,會依舊保持原有的代碼目錄結構,此時代碼目錄中就混入的.kt
文件,因爲不屬於資源剔除的範圍,天然就被當作資源文件打包進APK裏了。
在出現了源碼泄露的應用裏,我還發現了.aidl
文件,也就是IPC
通信時定義的接口文件。這類文件的泄露也是一樣的緣由形成的。
至此,這個源碼泄露案,也就告破了。
固然,說告破還有點早,畢竟上面給出的是推測,就算是真理,也是須要檢驗的。
回到自家工程的build.gradle
裏一查:
android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
}
}
}
複製代碼
果不其然,資源文件所在的目錄和源碼所在的目錄配置成了同一個。
至於出現這個問題緣由,筆者反思了一下。這個項目屬於比較早期的項目,代碼目錄結構遵循的是Eclipse
時代的規範,後面擁抱變化轉Android Studio
時,Gradle
默認的那套項目佈局規範和Eclipse
相差較大,爲了不對項目形成大的改動,因此採起了自定義目錄配置的作法,用較小的代價,完成了遷移。時過境遷,到了擁抱Kotlin
變化的時候,就出問題了。
明瞭問題的所在,定解決方案天然也就方便了:
resources.srcDirs = ['src']
配置。.kt
。這些方案裏,方案一有點簡單粗暴。對Android
項目來講,影響倒還好,由於不少資源都是放在assets
目錄裏,工程內不多會放這種資源文件了。
方案二適用於那些資源文件裏除了.kt
文件以外,還有別的資源文件的狀況,傳統java開發可能會有這種場景。
方案三是最穩妥,最合乎規範的推薦作法。將資源和代碼分開,使得相關文件在物理上保持了隔離,對整個項目來講,總體結構更加清晰。
對筆者這種狀況,更好的方式是作一次項目結構的改造,使之符合Gradle
的規範。
但歸根結底,這個問題屬於技術債務。不少時候,咱們在開發的過程當中,會爲了貪圖方便,本着儘量的減小影響面的想法,採起了一種折中的妥協的作法,度過了一時,但每每就埋下了禍根。
短時間內沒時間,確實能夠這麼作,但從長期來看,仍是要把債務還上的。只是時間的問題罷了。
最後的最後,建議你們自查一下,避免出現和筆者統一的狀況。尤爲是那些從Eclipse
時代轉過來的Android項目!
感謝閱讀到最後,但願本文對你有所幫助。若是以爲筆者的文章對你有所幫助,還請給個喜歡/感謝/贊。若有紕漏,也請不吝賜教。歡迎你們留言一塊兒討論。:-)
本文發出後,有朋友留言,指本文有標題黨的嫌疑。恕筆者沒法苟同。誠然,若有些朋友所言,不就是本身一個配置錯了,關Kotlin什麼事情,Kotlin乃無辜躺槍。
但筆者認爲,這當然不是編程語言的鍋,但倒是Kotlin工具鏈上的Kotlin Plugin
沒兼顧到這種場景緻使的安全漏洞。與之相對的Java Plugin
對這種場景就處理得周到得多。
雖然最後筆者將問題的緣由歸根於項目配置致使的問題,但筆者仍然認爲,這種狀況的發生,Kotlin Plugin
也有必定的責任。完善的工具鏈,能爲開發和使用帶來極大的便利,Kotlin Plugin
也不例外。筆者在Kotlin接入的配置教程裏,看到不少人在宣揚Kotlin
的引入很方便,方便的背後,卻可能會不當心帶來這麼大的安全隱患,筆者認爲,是頗有必要提醒使用了Kotlin
的各位的。
另外,安全問題的產生,每每都是小細節上的失誤致使的,而失誤,每每來自於人。愛因斯坦這樣說道:「只有兩種事物是無窮盡的——宇宙和人類的愚蠢」。
能趕上這個問題的項目,基本都是從Eclipse
時代過來的,這樣的項目,其具備的價值,料想是不言而喻的。筆者看到,有的同窗認爲,源碼泄露就泄露,愛誰看誰看。我的認爲,這是對項目的一種不負責任。
以上。
以前的標題《使用Kotlin或致使源碼泄漏!》,評論指出有蹭熱度的嫌疑,參考了承香墨影的推送,改爲《配置不當,或致使Kotlin源碼泄漏!》,更直觀和開門見山。:-)