求出現的原因是這樣的:
我們有一個 h5 頁面既需要嵌套到 App 內部進行用戶的信息填寫及提交,同時這個 h5 頁面也能夠單獨使用。 而這些用戶信息中就包括 `input`框選擇圖片。 <input type="file" name="avatar" id="avatar" />
出現了什么問題呢?
那么問題就出在 input 框這里,點擊這個 input 框,調起 android 手機自帶的拍照和選擇文件的對話框。
小米手機系統調起
只要選擇「圖片」或者「拍照」都沒有問題
問題就出現在選擇「取消」的時候
出現了問題,需要先解決點擊「取消」程序卡死的問題
這個問題,這篇文章已經介紹過了
H5 通過 input 標簽,調起 Android 手機相冊,點擊取消時手機卡住
如果之前沒有配置過,可以參考配置一下。
下面說今天的正題,就是點擊取消之后,如果之前頭像內有圖片,那么取消后會把之前的圖片干掉,展示出一個加載錯誤的樣子
原因找到了:當取消的時候,為了避免卡頓,返回了一個圖片的路徑,但是這個圖片路徑上對應的圖片是不存在的,從而導致了 H5 img 位置 顯示加載失敗
加載失敗
那么現在問題就來了:
如果不返回,就會卡頓;
如果返回了,就把 img 之前的展示圖片給干掉了
怎么辦呢?
我這邊的思路是:
將原來的 img 標簽內的 src 的內容存儲到本地,然后判斷:如果用戶點擊了取消,那么就將這個原來的 src 內容返回回去
那么這樣操作的話,就需要知道,如何拿到 img 標簽中的 src 的內容。
那么實際需要做這么幾部
1、這個需要和 H5 或者后臺溝通一下,將 H5 中的 這個頭像的 id 唯一,以保證能唯一找到這個頭像。
2、根據 id 找到這個 img 標簽后,再拿 src 中的內容存儲到本地
3、判斷用戶點擊取消時,將本地存儲的圖片 src 內容,返回給 H5。
第三點已經在
H5 通過 input 標簽,調起 Android 手機相冊,點擊取消時手機卡住
這個文章中提到過了,找到合適的位置直接返回即可。
所以本篇文章中的重點就是第一步:根據 id 找到 src 的內容。
1、創建 addJavascriptInterface 需要的「操作對象」,這個操作對象就是一個類,名字隨便起,不過內部的方法必須添加@JavascriptInterface注解
//內部類 final class InJavaScriptLocalObj { private static final String TAG = "MainActivity"; /** * @JavascriptInterface 必須要有的哦 * @param html * * 一旦檢測到 html 匹配到了要找的元素或者屬性,這里就會調用,否則不會調用這個方法 */ @JavascriptInterface public void showAvatar(String html) { Log.e(TAG, "showAvatar: " + html); } }
2、配置 webview
private void initWebView() { /** * 三項均需配置 */ webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new InJavaScriptLocalObj(), "local_obj"); webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { webView.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); /** * ambassador_avatar 是和后臺(h5)商議的唯一的 id */ view.loadUrl("javascript:window.local_obj.showAvatar(document.getElementById('ambassador_avatar').getAttribute('src'));"); } }); }
那么找元素關鍵的一句,就是
view.loadUrl("javascript:window.local_obj.showAvatar(document.getElementById('ambassador_avatar').getAttribute('src'));");
備注
找元素的方法很相似,就是跟 html 中的找 dom 節點一樣
可以移步到 w3school 逛網看一看
dom 元素查找方法
這里小總結一下
通過 id 查找 HTML 元素 通過標簽名查找 HTML 元素 通過類名查找 HTML 元素 通過 CSS 選擇器查找 HTML 元素 通過 HTML 對象集合查找 HTML 元素 var myElement = document.getElementById("intro");//返回單個元素 var x = document.getElementsByTagName("p");//返回元素列表 var x = document.getElementsByClassName("intro");//返回元素列表 var x = document.querySelectorAll("p.intro");//返回元素列表 var x = document.forms["frm1"];//返回元素列表
返回元素列表的方法在使用是 需要像數組那樣去取得對應的元素,如x[0]
拿到元素之后,通過 DOM 的文檔,拿到想要的屬性、值等等信息。
這樣就能通過存儲原來的圖片信息,在點擊取消的時候把信息返回,解決了本次需求的問題。
謝謝大家的收藏、關注、轉發,持續更新!
1、Android中利用webView調用網頁上的Js代碼。
Android 中可以通過webView來實現和Js的交互,在程序中調用Js代碼,只需要將webView控件的支持Js的屬性設置為true,然后通過loadUrl就可以直接進行調用,如下所示:
mWebView.getSettings().setJavaScriptEnabled(true); mWebView.loadUrl("javascript:test()");
2、網頁上調用Android中Java代碼的方法
在網頁中調用Java代碼,需要在webView控件中添加javascriptInterface。如下所示:
mWebView.addJavascriptInterface(new Object() { public void clickOnAndroid() { mHandler.post(new Runnable() { public void run() { Toast.makeText(Test.this, "測試調用java", Toast.LENGTH_LONG).show(); } }); } }, "demo");
在網頁中,只需要像調用Js方法一樣,進行調用就可以
<div id='b'><a onclick="window.demo.clickOnAndroid()">b.c</a></div>
3、Java代碼調用Js并傳參
首先需要帶參數的Js函數,如function test(str),然后只需在調用Js時傳入參數即可,如下所示:
mWebView.loadUrl("javascript:test('aa')");
4、Js中調用Java函數并傳參
首先一樣需要帶參數的函數形式,但需注意此處的參數需要final類型,即得到以后不可修改,如果需要修改其中的值,可以先設置中間變量,然后進行修改。如下所示:
mWebView.addJavascriptInterface(new Object() { public void clickOnAndroid(final int i) { mHandler.post(new Runnable() { public void run() { int j = i; j++; Toast.makeText(Test.this, "測試調用java" + String.valueOf(j), Toast.LENGTH_LONG).show(); } }); } }, "demo");
然后在html頁面中,利用如下代碼:
<div id='b'><a onclick="window.demo.clickOnAndroid(2)">b.c</a></div>,
即可實現調用
web安全對iOS開發者來說重要嗎?重要!APP中通常會使用很多web頁面,例如廣告、登錄流程、閃屏,或者需要使用跨平臺功能的時候。你可能在頁面中僅僅一部分使用web,也可以整個頁面都是webView,甚至做一個web app。因此web安全對于app來說非常重要。
來自web的安全攻擊有以下幾種:
本文將針對這三種攻擊類型,給出安全防御措施。
網絡傳輸相信大家都很熟悉了,安全的傳輸能夠保證接收到的數據來自可信任的站點,并且在傳輸工程中不會被篡改。安全傳輸是其它安全措施的基礎,采取的措施包括:
Allow Arbitrary Loads in Web Content 這個開關一定要置為 NO!
web的內容可以來自任何站點,例如,webView上的一張圖片可以來自任何服務器,也可以從任意服務器上加載一個腳本或iframe。需要注意的是要當心來自其它服務器的資源。跨域的保護已經有20多年的歷史,并且形成了基本原則--同源策略:只有和頁面來源相同的腳本才會被該頁面執行。例如iframe來自不同的域名,同源策略不允許加載這個iframe。僅僅靠同源策略還是不夠的,還需要采取其它的防御措施。
服務器可能會發生異常導致下發錯誤的資源使得web發生crash,但是開發者通常是知道所要請求哪個資源的,在腳本里面增加一個檢查簽名。如果簽名匹配則認為是下發了正確的資源,如果不匹配仍然可以正常工作,此時嘗試從頁面的資源里查找或者從自己的服務器重新加載。這樣做雖然降低了性能,但是提升了安全性。
<script src="https://cdn.example/framework.js" integrity="sha256-8WqyJLuWKRB...oZkCnxQbWwJVw="> </script> window.framwork || // reload from own domain
HTTP response: :status:200 Content-Security-Policy: default 'self'; // No inline script-src cdn.example; frame-src social.example; frame-ancestors news.example;
HTTP response的Header里面,default設置成自己,默認只能加載同源的資源;script-src和frame-src 分別指定可信任的腳本和iframe的來源;frame-ancestor設置成news.example,指定只有news.example可以iframe我們的web。
另外不使用inline屬性的腳本也是一種防御措施,不使用inline腳本,只從文件加載腳本,這么做分離了邏輯和文件,更加安全。
HTTPOnly cookies作為一種安全措施,已經有至少15年的使用歷史。在這之前script通過document.cookie這個強大的api能拿到文檔的cookie,留下安全隱患。HTTPOnly cookies能夠阻止這種情況,只允許HTTP請求訪問cookie,禁止使用script訪問cookie。它的使用方式很簡單,只需要在HTTP response的Header里面加上HttpOnly這一項,如下
HTTP response: :status:200 Set-Cookie: auth = abc...123; HttpOnly;
在HTTP response的Header里面將SameSite cookies這一項設置為Strict,那么將不允許把cookie從一個域名發送到另一個域名。例如其他人的web里面嵌入了我們的web,如果我們的服務器HTTP response的Header里面SameSite cookies = Strict,那么其他人將無法使用他的cookie來訪問我們的服務器。
HTTP response: :status:200 Set-Cookie: auth = abc...123; HttpOnly; SameSite=strict
Cross-Origin-Resource-Policy是推出的新功能。之前web可以加載任意web中的資源,例如圖片或者script。在HTTP response的Header里面將Cross-Origin-Resource-Policy這一項設置為Same,將不允許別人的web向我們的服務器請求圖片或者script,但是我們自己的web可以。
HTTP response: :status:200 Cross-Origin-Resource-Policy:Same
Cross-Origin-Window-Policy也是新推出的功能。之前通過window.open這個強大的api,其他人的web可以在新窗口中打開我們域名下的web,通過一些手段可以修改我們的web,導航到攻擊者指定的頁面。在HTTP response的Header里面將Cross-Origin-Resource-Policy這一項設置為Deny,將阻止其他人修改我們web中的內容,當然別人仍然還是可以打開我們的web。Cross-Origin-Resource-Policy適用于希望使用post message 進行窗口間通信,但是不想讓別人控制我們自己web內容的情況。
HTTP response: :status:200 Cross-Origin-Window-Policy:Deny
Cross-Origin Attacks
Cross-Site Scripting
例如我們的web里面有一個文本框,用戶可以輸入文字,如下圖。假如攻擊者注入了這么一段腳本,如果沒有采取防御措施,那么我們web的cookie就會被盜取。
在HTTP response的Header中添加HTTPOnly這一項,就能阻止腳本訪問文檔的cookie,從而防御跨域腳本攻擊。
另外一種防御手段是Content-Security-Policy,如下
HTTP response: :status:200 Content-Security-Policy: default-src 'self'; // No inline
Content-Security-Policy能保證拒絕加載外部來源的腳本,并且不使用inline屬性的腳本,只從文件中加載腳本。
例如我們的web需要從某個外部資源裝載一個framework,攻擊者可能攔截這個請求,并把它重定向到自己的攻擊腳本上,如下圖
使用Content-Security-Policy中script-src這個屬性可以指定信任的腳本來源,并且在引用資源的時候指定來源和校驗簽名,如下
在HTTP response中:
HTTP response: :status:200 Content-Security-Policy: default-src 'self'; script-src cdn.example;
在HTML中:
<script src="https://cdn.example/framework.js" integrity="sha256-8WqyJLuWKRB...oZkCnxQbWwJVw="> </script> window.framwork || // reload from own domain
攻擊者可能在自己的web中嵌入我們的web,然后向我們的服務器發起一個偽造的網絡請求(使用的是攻擊者網站的cookie),如下圖
如果采取了防御措施,將HTTP response的Header里面的SameSite設置為strict,那么就會禁止攻擊者網站的cookie發動到我們的服務器上面,如下
HTTP response: :status:200 Set-Cookie: auth=abc...123; SameSite=strict
防御措施有:
Speculative execution 的定義:預測執行類似于批量執行條件判斷語句,例如計算機大量執行"x是否會造成數組array越界"這條指令,就能推測出這個數組的長度,進一步推測出這個數組在內存緩沖區中的地址邊界。利用緩沖區溢出這種攻擊手段,可以向web中注入攻擊腳本。當x超過數組邊界的時候,本來應該執行越界的error回調,但是確取出了攻擊腳本并執行,造成數據泄露。顯然只靠同源策略是無法防御這種攻擊的,因為攻擊腳本和文檔處在同一個域名下,并且在同一個線程中。
防御預測執行攻擊的方法是確保web內容和其他iframe(例如攻擊腳本)處在不同的線程中。
以Safari app為例,WKWebView會單獨分離出一個NetWork線程用于處理添加cookie等邏輯,而且每個網頁處在不同的線程當中,所以evil網頁是無法通過預測執行攻擊手段攻擊我們的頁面。而且因為NetWork線程也是獨立的,所以evil網頁也無法通過預測執行攻擊手段拿到重要數據,例如cookie。
如果使用UIWebView,所有的web包括NetWork線程都在app的同一個線程中,所以是無法防御預測執行攻擊手段的。
Content security policy的封鎖功能是處于Network線程中,和web線程是分離的,因此可以防御預測執行攻擊手段。
例如web要加載一個廣告iframe,但是這個廣告iframe被重定向到了一個攻擊腳本,如果使用了Content security policy,如下,因為攻擊腳本不在信任的frame-src里面,所以會禁止加載。還有一種情況,攻擊者的web引入了我們的web,因為設置了frame-ancestors為none,所以會禁止攻擊者網站引入我們的web,從而防御攻擊。
HTTP response: :status:200 Content-Security-Policy: default-src 'self'; frame-src ad.example social.example frame-ancestors 'none'
HttpOnly cookies 和 SameSite cookies的封鎖功能也是處于Network線程中,和web線程是分離的,因此可以防御預測執行攻擊手段。HttpOnly cookies能夠禁止攻擊者通過腳本拿到cookie。SameSite cookies設為strict能夠禁止cookie從一個域發送到另一個域。
Cross-Origin-Resource-Policy
Cross-Origin-Resource-Policy的封鎖功能也是處于Network線程中,和web線程是分離的,因此可以防御預測執行攻擊手段。Cross-Origin-Resource-Policy設置成Same能禁止攻擊者的web加載我們網站的資源。
Window Control Attacks
Cross-Origin-Window-Policy
攻擊者的頁面可以通過window.open這個api在新的窗口打開我們的web,攻擊者趁我們不注意的時候,把我們的頁面導航到釣魚頁面,然后誘導用戶填寫用戶名和密碼,這樣就竊取到了用戶信息。把HTTP response Header里面的Cross-Origin-Window-Policy設置為Deny,能夠禁止攻擊者修改我們的web,這樣攻擊者就無法導航到釣魚頁面。
總結
每種安全措施防御的攻擊類型
*請認真填寫需求信息,我們會在24小時內與您取得聯系。