eb前端面試題
UlWebView是i〇S SDK中渲染網面的控件,在顯示網頁的時候,我們可以hack網頁 ,然后顯示想顯示的內容。其中就要用到JavaScript的知識,而UlWebView與javascript交互的方法就是stringByEvaluatingJavaScriptFromString,有了這個方法我們可以通過objc調用javascript,可以注入javascript。
Js調用〇C方法原理就是利用UIWebView重定向請求,傳一些命令到我們的 UIWebView,在UIWebView的delegate的方法中接收這些命令,并根據命令執行相應的objc 方法。這樣就相當于在javascript中調用objc的方法。
在android中,我們有固有組件webview,經過設置可以讓它支持我們js的渲染,然 后在代碼中設置(WebViewClient/WebChromeClient)讓應用跳轉頁面時在本webview中跳轉,通過webview.loadurl (String str)方法可以在需要的地方加載我們前端的頁面或者調用前端所定義的方法。
(wv.loadUrl(“javascript:sendDataToAndroid(‘我是來自js的呦,你看到了 嗎’)”);),我們再通過JavascriptInterface接口設置我們前端和android通訊的標識, wv.addJavascriptInterface(new MJavascriptInterface(getApplicationContext()), “WebViewFunc”); 這樣前端就可以在頁面上調用我們的方法了,funl方法是在android中定義的Window.WebViewFunc.fun1 ()。
總之,前端和android或者ios進行結合開發,我們稱之為混合開發,原理就是在原生 的開發語言中,我們提供了一個組件webview,這個組件就是我們的原生語言的瀏覽器,但是我們得自行設置讓其能夠完美支持我們的應用,需要設置對應的標識,然后連接起來,我們稱之為JavascriptInterfac。
以上就是酷仔今天整理提供的Web前端開發面試題,希望為Web前端同學提供了有用的面試素材,以后酷仔每日均會提供Python及Web相關的習題。
言
WKWebView是iOS8 出來的瀏覽器控件,用來取代UIWebView.對于WKWebView與UIWebView的對比特點,這里就不過多的敘述,都算是老生常談的問題了,網上的說明也很多.近來在做Web端,需要植入移動端,并且做JS交互工作.以前寫過的JavaScript:淺談iOS與H5的交互-JavaScriptCore框架是用于UIWebView.在WKWebView并不適用了,自己做的過程中遇到一些坑,在這里總結一下,做一下記錄.
WKWebView加載本地 html文件
現在的項目要求就是使用存儲在本地的html文件 js文件 css文件 img圖片等文件.我使用HBuilder創建了一個Demo工程.里面包含了基本的文件以及圖片資源.如下所示.然后拖到Xcode工程中.
然后我們把整個Html工程文件夾導入工程中.
WKWebView 在iOS 9 有新的加載本地方法- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));.但是我看了網上有一些博客說- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;并不能加載本地html文件.其實兩者都能加載.只是需要把路徑寫對.第一個方法就不過多敘述了.網上有很多的博客.這里我就用第二個方法來看一下如何加載.
NSString *path=[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"index.html"];
NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]];
[_mainWebView loadRequest: request];
運行效果圖如下.
Xcode工程中 html文件 加載js文件 css文件 img文件
上面我們加載了html.可是css樣式 .img文件和js文件都沒有加載出來.那么我們該如何解決呢?(html原始加載圖如下所示.)
對于css文件、img文件 ,js文件我們只需要把html文件中的文件夾路徑刪除即可.如下所示.
???????? 注意:這里是使用的- (WKNavigation *)loadRequest:(NSURLRequest *)request;方式加載的網頁.所有如上設置即可.如果使用的是loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL或者loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL;都需要設置本地資源文件所對應的路徑! 我們只需要把資源文件所對應的路徑設置給readAccessURL 和 baseURL即可(). 例如下面所示.
//假定都在工程根目錄之下.
NSURL *baseURL=[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
[_mainWebView loadHTMLString:[self loadHtmlString] baseURL:baseURL];
對于js文件,有時候我們發現我們就算如上刪除了js文件夾的路徑依然不能使用.這是為什么呢?.這里就要去檢測查看工程的設置,是否把js文件當成一個可編譯文件使用了.我們需要把它移動到資源文件中.這樣就能正常加載了.如下圖所示.
WKWebView中警告窗 確認面板 輸入框的顯示
相比于UIWebView,WKWebView對警告窗 確認面板 輸入框并不能直接顯示.是通過WKUIDelegate代理方法收到對應的回調方法.如下所示.
//接收到警告面板
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
//接收到確認面板
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
//接收到輸入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
我們只需要對上面的回調方法進行實現即可實現顯示警告窗 確認面板 輸入框等需求.
WKWebView中OC方法調用JS方法
在WKWebView OC方法調用JS方法方法比較簡單.我們只需要使用如下方法即可.
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
看一下我寫的例子.在index.js中定義一個方法.方法內容為彈出一個警告框.代碼如下所示.
function alertAction(message) {
alert(message);
}
然后在ViewController控制器中定義一個Button.定義它的點擊方法.代碼如下所示.
- (UIButton *)alertButton{
if (_alertButton==nil) {
_alertButton=[[UIButton alloc] initWithFrame:CGRectMake(KMainWidth*0.2, KMainHeight - 60, KMainWidth * 0.6, 40)];
_alertButton.backgroundColor=[UIColor colorWithRed:250/255.0 green:204/255.0 blue:96/255.0 alpha:1.0];
_alertButton.layer.cornerRadius=6.0f;
_alertButton.layer.masksToBounds=YES;
_alertButton.titleLabel.font=[UIFont systemFontOfSize:16];
[_alertButton setTitle:@"彈出彈窗" forState:UIControlStateNormal];
[_alertButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_alertButton addTarget:self action:@selector(alertButtonAction) forControlEvents:UIControlEventTouchUpInside];
}
return _alertButton;
}
- (void)alertButtonAction{
[self.mainWebView evaluateJavaScript:@"alertAction('OC調用JS警告窗方法')" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
NSLog(@"alert");
}];
}
因為彈窗不能直接顯示.所以我們實現了對應的代理方法.如下所示.
//接收到警告面板
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
UIAlertController *alert=[UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action=[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
completionHandler();//此處的completionHandler()就是調用JS方法時,`evaluateJavaScript`方法中的completionHandler
}];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
}
這時候我們點擊按鈕就會調用對應的JS方法了.相比于JavaScriptCore框架還是非常簡單的.效果圖如下所示.
WKWebView中JS方法調用OC方法
上一個模塊我們看到了OC方法調用JS方法.那么JS方法調用OC方法呢?我們也只需要幾步就可以完成調用.
第一步.我們需要在WKWebView創建的過程中初始化添加ScriptMessageHandler.(命名自定例如:currentCookies.如下所示)
WKWebViewConfiguration *configuration=[[WKWebViewConfiguration alloc] init];
WKUserContentController *userController=[[WKUserContentController alloc] init];
configuration.userContentController=userController;
_mainWebView=[[WKWebView alloc] initWithFrame:CGRectMake(0, 0, KMainWidth, KMainHeight) configuration:configuration];
[userController addScriptMessageHandler:self name:@"currentCookies"];
然后實現代理方法.監聽JS的回調.為了查看效果,我們仍然使用彈窗的形式展示我們的回調信息.代碼如下所示.
//JS調用的OC回調方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if ([message.name isEqualToString:@"currentCookies"]) {
NSString *cookiesStr=message.body;
NSLog(@"當前的cookie為: %@", cookiesStr);
UIAlertController *alert=[UIAlertController alertControllerWithTitle:@"提示" message:@"JS調用的OC回調方法" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action=[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:action];
[self presentViewController:alert animated:YES completion:nil];
}
}
然后在Html文件中添加點擊方法.
<div id="button_div" onclick="buttonDivAction()">
點擊調用OC方法
</div>
緊接著.在js文件中實現點擊事件.這時候要注意的是ScriptMessageHandler的名稱要與上面定義的一致.
function buttonDivAction() {
window.webkit.messageHandlers.currentCookies.postMessage({
"body": "buttonActionMessage"
});
}
然后我們點擊網頁中對應的div就會出現對應的彈窗.效果圖如下所示.
并且控制臺打印信息如下所示.
總結
相比于UIWebView,WKWebView確實更加的方便快捷.本篇博客就到這里了.如果有任何問題,歡迎在評論區回復騷棟.感謝觀看,最后還是附上本篇博客的Demo傳送門.
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小時內與您取得聯系。