當前位置:
首頁 > 知識 > 想寫無Bug的安全代碼->看防禦性編程的藝術

想寫無Bug的安全代碼->看防禦性編程的藝術

一提到「防禦性編程」,大家都會感覺,這個話題很大,不知從何說起,該說哪些具體內容。

我做這篇文章的源頭,是我已經做了很多很多相關前端及後端數據流校驗的事情。對測試同學給我提出的所有bug做了整體的統計促使我對「防禦性編程」的思考。我想絕大多數的程序bug都是因為代碼「防禦性」做得不夠好而導致的,而導致代碼「防禦性」不夠完善的原因又是多種多樣的。

我們做防禦性編程,無非一個目的——打造高質量的模塊(或程序)。然而,相信大家都清楚,不可能僅憑做好了「防禦性」來評價模塊(或程序)的質量高與低。同樣的,即使我們搭建了十分健壯的代碼「防禦性」,我們也不可能確保不會有任何bug的產生。

「防禦性編程」——它更多的,是一種努力。

一、理解之

引入一篇文章——什麼是防禦性編程,它對「防禦性編程」的定義——

防禦性編程是一種細緻、謹慎的編程方法。為了開發可靠的軟體,我們要設計系統中的每個組件,以使其儘可能地「保護」自己。我們通過明確地在代碼中對設想進行檢查,擊碎了未記錄下來的設想。這是一種努力,防止(或至少是觀察)我們的代碼以將會展現錯誤行為的方式被調用。

防禦性編程是一種編程習慣,是指預見在什麼地方可能會出現問題,然後創建一個環境來測試錯誤,當預見的問題出現的時候通知你,並執行一個你指定的損害控制動作,如停止程序執行,將用戶重指向到一個備份的伺服器,或者開啟一個你可以用來診斷問題的調試信息。

再次思考這個定義,其實它真正要做的,是「當預見的問題出現的時候通知你,並執行一個你指定的損害控制動作」。而對於的性質,可以理解為「是一種努力,是一種編程習慣」。

而對於「防禦性編程」的作用,其中的兩張圖足以說明——

以前可能這樣做——

現在可能這樣做——

「防禦性編程」幫助我們從一開始就編寫正確的軟體,而不再需要經歷「編寫-嘗試-編寫-嘗試……」的循環過程。

當然,防禦性編程並不能排除所有的程序錯誤。但是問題所帶來的麻煩將會減少,並易於修改。防禦性程序員只是抓住飄落的雪花,而不是被埋葬在錯誤的雪崩中。

防禦性編程是一種防衛方式,而不是一種補救形式。

OK,對於「防禦性編程」概念的理解就說到這兒。不得不多說的一點是——每種防禦性的做法都需要一些額外的工作,從而導致它降低了代碼的效率。那麼,具體有哪些去做「防禦性編程」的技巧呢?

二、使用之

引入文章——防禦性編程技巧,直接枚舉出裡面的技巧——

1> 使用好的編碼風格和合理的設計2> 不要倉促地編寫代碼 3> 不要相信任何人 4> 編碼的目標是清晰,而不是簡潔5> 不要讓任何人做他們不該做的修補工作 6> 編譯時打開所有警告開關 7> 使用靜態分析工具 8> 使用安全的數據結構9> 檢查所有的返回值 10>審慎地處理內存(和其他寶貴的資源) 11>在聲明位置初始化所有變數12>儘可能推遲一些聲明變數 13>使用標準語言工具 14>使用好的診斷信息日誌工具 15>審慎地進行強制轉換16>其他 a> 審慎地進行強制轉換 b> 提供默認的行為 c> 檢查數值的上下限

讀到每一點,相信共性的問題,大家都親身接觸過,相信大家都有不同的感悟與理解。隨著經驗的積累,相信大家對具體問題如何去做「防禦性」的方式也是不同的。總之,都是對程序的一種努力。

三、數據流處理

都知道「防禦性編程」的範圍很大,在這裡,我想對其中的一點,做深入的研究說明——數據流處理。

拿web請求的流程來講,用戶首先從瀏覽器端輸入數據、觸發請求,到伺服器端程序接收數據、處理業務邏輯,再到DB庫對數據的持久化存儲。整個數據流走下來,都需要經歷「風風雨雨」的數據流的防禦處理過程。

對於前端頁面及js對數據流校驗的處理,不妨看一下我的這兩篇文章——談談代碼健壯性之前端校驗和談談代碼健壯性之極限值處理(防禦性編程)

對於後端(這裡主要使用java)的處理,對於數據流的校驗,我們多用斷言(Assert)來進行校驗處理。如——

//字元串propertyName不可為空Assert.hasText(propertyName);//對象objectName不可為空Assert.notNull(objectName);//……

我們當然也遇到賦予默認值的情況,如——

String propertyName = (StringUtils.isNotEmpty(name) ? name :null);//......

單單判空遠遠不夠。舉個例子,我們限制用戶登錄密碼在6到16位且不可包含「,,.。%$」等特殊字元,具體的後端程序代碼實現就不說了。只是想說明的是,可不要因為客戶端做了校驗,就忘記了在伺服器端做校驗。

需要額外提的是,對於面向用戶的應用來說,我們確實需要在前端及後端同時進行數據流校驗,且校驗規則是相同的。如果我們的校驗規則僅僅去寫一次,就能夠同時作用於前端及後端,那就很方便去維護了。我們需要一個中間件去配置這些校驗的規則。簡單舉個xml的配置方式,如——

這樣,不管是前端還是後端,我們可以通過解析這個xml文件來確保兩者的校驗規則是相同的。

OK,到這裡,後端的數據流處理介紹就到這裡了,緊接著就介紹資料庫端如何處理數據流了(這裡我以mysql為例)。

首先一點,便是插件數據時,對應的每一個數據項的默認值的處理。在創建表的語句中進行添加,如——

CREATE TABLEt_xxx { property_nameVARCHAR(255)notNULLDEFAULT COMMENT 欄位注釋 , …}

這樣也就很大程度上避免了臟數據的存儲。再舉一個例子,我們在多表連接查詢的時候,常常會碰到查詢null項,這樣我們就會用到查詢賦予默認值這樣類似的處理了,比如——

SELECTt1.xxx, IFNULL(yyy,)FROMt1LEFTJOINt2ONt1.id=t2.zzz_id

OK。資料庫端的數據流校驗處理介紹到這裡。

四、總結

先引入這樣一句話——

軟體濫用者形形色色,從利用程序小缺陷的不守規則的用戶,到想盡辦法非法進入他人系統的職業黑客。有太多的程序員在不經意間為這些人留下了可隨意通過的後門。隨著網路化計算機的興起,粗心大意所帶來的後果變得愈來愈顯著了。

許多大型軟體開發公司終於意識到了這種威脅,開始認真思考這個問題,將時間和資源投入到嚴謹的防禦性編碼工作中。

相信大家都能夠體會到做好「防禦性編程」的重要性。同時,我們需要知道,做好「防禦性編程」,我們往往要多花出3倍的時間去處理(遠遠不單單是數據流的處理,如思考代碼嚴謹性、思考信息提示、思考代碼走向等等等等)。

我想最重要的是,如果你想快速開發出高質量的模塊,不僅需要經驗的不斷累積,培養數據流的防禦性編程思維同樣不可缺少。

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 PHP技術大全 的精彩文章:

Nginx.conf配置文件全面解析
3980元的Hadoop大數據視頻教程限量領取!

TAG:PHP技術大全 |

您可能感興趣

Tania Bruguera:不想做古巴總統的行為作品不是好藝術家
Illustrator繪製復古風格的手繪藝術字教程
在Katie Eraser的抽象繪畫藝術里,感受安全和穩定
YT先鋒丨Tania Bruguera: 不想做古巴總統的行為作品不是好藝術家
用油畫的質感打造時裝影像,與空靈的音符和鳴的藝術家Anna Danilova
藝術 | Martin Margiela,神秘底色下的人物肖像
CG插畫藝術家 Alberto Mielgo的現代科幻作品
飛翔的夢:藝術家 Brigitte May 動物水彩繪畫
H&M與版畫藝術家Anna Glover合作推出膠囊系列:將春天韻味裝進衣櫥!
插畫:喬治亞藝術家Merab Gagiladze作品欣賞
南非藝術家 Margaret Berg 治癒系水彩作品
Super Stars 中的隱藏畫家:藝術果真是相通的
深度了解繆繆 (Miu Miu) 、普拉達 (Prada) 女裝總設計師Antonio Fontana:藝術家的一顆私心!
<中國詩詞大會>酈波點評<長恨歌>,說楊貴妃的愛情是藝術家的愛情
獨特神態:義大利寫實藝術家Ester Curini 動物繪畫
水彩藝術家 Jean Haines 的繪畫作品
羅馬尼亞水彩藝術家 Corneliu Dragan 繪畫作品
自學派:英國水彩藝術家 Yvonne Harry 繪畫作品
玩具總動員:藝術家Yuliya Martynova 水彩繪畫
素描寫生:來自西班牙藝術家 Miguel Angel Oyarbid 繪畫作品