JAVA框架面試題整理之—第四篇

weixin_34253539發表於2017-12-05

168、什麼是XSS攻擊?什麼是SQL隱碼攻擊?什麼是CSRF攻擊?

答:

- XSS(Cross Site Script,跨站指令碼攻擊)是向網頁中注入惡意指令碼在使用者瀏覽網頁時在使用者瀏覽器中執行惡意指令碼的攻擊方式。跨站指令碼攻擊分有兩種形式:反射型攻擊(誘使使用者點選一個嵌入惡意指令碼的連結以達到攻擊的目標,目前有很多攻擊者利用論壇、微博釋出含有惡意指令碼的URL就屬於這種方式)和持久型攻擊(將惡意指令碼提交到被攻擊網站的資料庫中,使用者瀏覽網頁時,惡意指令碼從資料庫中被載入到頁面執行,QQ郵箱的早期版本就曾經被利用作為持久型跨站指令碼攻擊的平臺)。XSS雖然不是什麼新鮮玩意,但是攻擊的手法卻不斷翻新,防範XSS主要有兩方面:消毒(對危險字元進行轉義)和HttpOnly(防範XSS攻擊者竊取Cookie資料)。

- SQL隱碼攻擊是注入攻擊最常見的形式(此外還有OS注入攻擊(Struts 2的高危漏洞就是通過OGNL實施OS注入攻擊導致的)),當伺服器使用請求引數構造SQL語句時,惡意的SQL被嵌入到SQL中交給資料庫執行。SQL隱碼攻擊需要攻擊者對資料庫結構有所瞭解才能進行,攻擊者想要獲得表結構有多種方式:(1)如果使用開源系統搭建網站,資料庫結構也是公開的(目前有很多現成的系統可以直接搭建論壇,電商網站,雖然方便快捷但是風險是必須要認真評估的);(2)錯誤回顯(如果將伺服器的錯誤資訊直接顯示在頁面上,攻擊者可以通過非法引數引發頁面錯誤從而通過錯誤資訊瞭解資料庫結構,Web應用應當設定友好的錯誤頁,一方面符合最小驚訝原則,一方面遮蔽掉可能給系統帶來危險的錯誤回顯資訊);(3)盲注。防範SQL隱碼攻擊也可以採用消毒的方式,通過正規表示式對請求引數進行驗證,此外,引數繫結也是很好的手段,這樣惡意的SQL會被當做SQL的引數而不是命令被執行,JDBC中的PreparedStatement就是支援引數繫結的語句物件,從效能和安全性上都明顯優於Statement。

- CSRF攻擊(Cross Site Request Forgery,跨站請求偽造)是攻擊者通過跨站請求,以合法的使用者身份進行非法操作(如轉賬或發帖等)。CSRF的原理是利用瀏覽器的Cookie或伺服器的Session,盜取使用者身份,其原理如下圖所示。防範CSRF的主要手段是識別請求者的身份,主要有以下幾種方式:(1)在表單中新增令牌(token);(2)驗證碼;(3)檢查請求頭中的Referer(前面提到防圖片盜連結也是用的這種方式)。令牌和驗證都具有一次消費性的特徵,因此在原理上一致的,但是驗證碼是一種糟糕的使用者體驗,不是必要的情況下不要輕易使用驗證碼,目前很多網站的做法是如果在短時間內多次提交一個表單未獲得成功後才要求提供驗證碼,這樣會獲得較好的使用者體驗。

9369836-e70818933075126a

補充:防火牆的架設是Web安全的重要保障,ModSecurity是開源的Web防火牆中的佼佼者。企業級防火牆的架設應當有兩級防火牆,Web伺服器和部分應用伺服器可以架設在兩級防火牆之間的DMZ,而資料和資源伺服器應當架設在第二級防火牆之後。

169. 什麼是領域模型(domain model)?貧血模型(anaemic domain model)和充血模型(rich domain model)有什麼區別?

答:領域模型是領域內的概念類或現實世界中物件的視覺化表示,又稱為概念模型或分析物件模型,它專注於分析問題領域本身,發掘重要的業務領域概念,並建立業務領域概念之間的關係。貧血模型是指使用的領域物件中只有setter和getter方法(POJO),所有的業務邏輯都不包含在領域物件中而是放在業務邏輯層。有人將我們這裡說的貧血模型進一步劃分成失血模型(領域物件完全沒有業務邏輯)和貧血模型(領域物件有少量的業務邏輯),我們這裡就不對此加以區分了。充血模型將大多數業務邏輯和持久化放在領域物件中,業務邏輯(業務門面)只是完成對業務邏輯的封裝、事務和許可權等的處理。下面兩張圖分別展示了貧血模型和充血模型的分層架構。

貧血模型

9369836-8b579baad987437b

充血模型

9369836-f673347c07d76174

貧血模型下組織領域邏輯通常使用事務指令碼模式,讓每個過程對應使用者可能要做的一個動作,每個動作由一個過程來驅動。也就是說在設計業務邏輯介面的時候,每個方法對應著使用者的一個操作,這種模式有以下幾個有點:

- 它是一個大多數開發者都能夠理解的簡單過程模型(適合國內的絕大多數開發者)。

- 它能夠與一個使用行資料入口或表資料入口的簡單資料訪問層很好的協作。

- 事務邊界的顯而易見,一個事務開始於指令碼的開始,終止於指令碼的結束,很容易通過代理(或切面)實現宣告式事務。

然而,事務指令碼模式的缺點也是很多的,隨著領域邏輯複雜性的增加,系統的複雜性將迅速增加,程式結構將變得極度混亂。開源中國社群上有一篇很好的譯文《貧血領域模型是如何導致糟糕的軟體產生》對這個問題做了比較細緻的闡述。

170. 談一談測試驅動開發(TDD)的好處以及你的理解。

答:TDD是指在編寫真正的功能實現程式碼之前先寫測試程式碼,然後根據需要重構實現程式碼。在JUnit的作者Kent Beck的大作《測試驅動開發:實戰與模式解析》(Test-Driven Development: by Example)一書中有這麼一段內容:“消除恐懼和不確定性是編寫測試驅動程式碼的重要原因”。因為編寫程式碼時的恐懼會讓你小心試探,讓你迴避溝通,讓你羞於得到反饋,讓你變得焦躁不安,而TDD是消除恐懼、讓Java開發者更加自信更加樂於溝通的重要手段。TDD會帶來的好處可能不會馬上呈現,但是你在某個時候一定會發現,這些好處包括:

- 更清晰的程式碼 — 只寫需要的程式碼

- 更好的設計

- 更出色的靈活性 — 鼓勵程式設計師面向介面程式設計

- 更快速的反饋 — 不會到系統上線時才知道bug的存在

補充:敏捷軟體開發的概念已經有很多年了,而且也部分的改變了軟體開發這個行業,TDD也是敏捷開發所倡導的。

TDD可以在多個層級上應用,包括單元測試(測試一個類中的程式碼)、整合測試(測試類之間的互動)、系統測試(測試執行的系統)和系統整合測試(測試執行的系統包括使用的第三方元件)。TDD的實施步驟是:紅(失敗測試)- 綠(通過測試) – 重構。關於實施TDD的詳細步驟請參考另一篇文章《測試驅動開發之初窺門徑》

在使用TDD開發時,經常會遇到需要被測物件需要依賴其他子系統的情況,但是你希望將測試程式碼跟依賴項隔離,以保證測試程式碼僅僅針對當前被測物件或方法展開,這時候你需要的是測試替身。測試替身可以分為四類:

- 虛設替身:只傳遞但是不會使用到的物件,一般用於填充方法的引數列表

- 存根替身:總是返回相同的預設響應,其中可能包括一些虛設狀態

- 偽裝替身:可以取代真實版本的可用版本(比真實版本還是會差很多)

- 模擬替身:可以表示一系列期望值的物件,並且可以提供預設響應

Java世界中實現模擬替身的第三方工具非常多,包括EasyMock、Mockito、jMock等

http://bbs.itheima.com/forum.php?mod=viewthread&tid=383781

相關文章