一月 9, 2012

hoamon's sandbox
hoamon
hoamon's sandbox is about »

tag cloud

» 不應該在資料庫中紀錄使用者的明碼密碼

看到這個有趣的 Blog :「我的密碼沒加密」。我才知道這世上不懂『不應該在資料庫中紀錄使用者的明碼密碼』的程式設計師是如此之多。

這本應是菜鳥程式設計師才應該犯下的錯,沒想到連存在好幾年的「綠界」都有。我真的不願相信這是事實。話說回來,對一個合格的 Linux/Unix 管理員,不能有明碼密碼根本就是常識。

過去,我還想用 PGP 驗證來取代『在伺服器資料庫紀錄使用者密碼』,這法子絕對能確保「使用者密碼」不會外洩。只是,我沒遇到那個使用者能接受自己產生一對公私錀,利用它們來作登入的。

雖然我沒作出個 PGP 驗證的實際上線系統,但 StartSSL.com 作到了,它不是用 PGP 加解密,是另一種公私錀原理。所以外國月亮比較圓是真的。

在我所撰寫過的系統中,只要有帳號認證的,一定會在伺服器端用 md5/sha1 作 hash ,另外也會在瀏覽器端用 javascript 作 md5 hash 。

伺服器端 hash 是防自己人及入侵者,防入侵者不用講了,這是一定要的,但「自己人」為什麼要防呢? 想想看,一個系統內幾千甚至上萬個會員的帳號/密碼都可以給自己人看,那這些自己人難道不會換工作,難道不會對老闆不爽,難道不會被「社交」,將密碼變暗碼,除了保護使用者外,也是為自己人免責,至少使用者自己被社交了,他也不能栽髒我們。

而瀏覽器端的 md5 hash 又是為了什麼? 因為我寫的網頁系統少能跑在 https 上,無法為使用者輸入的密碼作加密以防止中間人攻擊。所以我只好用 md5 函式 hash 過使用者明碼密碼,這雖無法完全避免使用者帳戶被盜用(在明碼傳輸中,它就是有可能遭受中間人攻擊),但至少讓它們難以反推用戶的原始密碼。

另外也曾在一個「歷史系統」中,在瀏覽器端部份是使用 rsa 加密的。因為它之前只有使用「伺服器端 hash」作保護,而當我要再加上「瀏覽器端 hash 」功能時,會面臨「無法使用它的明碼密碼來作自我 hash 」。

是的, hash 也是有技巧的,不要用同一個 salt key 作,要不然入侵者破了一個使用者密碼後,其他的也都猜出來了。所以瀏覽器端,我都是用使用者原始密碼內的某個字去當 salt 來作 hash 的。

於是在「歷史系統」中,要把它一次轉成「有瀏覽器端 hash 」功能的話,勢必要每個使用者回來登入一次,我才有機會將系統轉移。這不是件容易的事。退而求其次,使用 rsa 加密就是不錯的方法。這方法是某個學弟找到的,原本我還不知道有原生的 js 函式庫能作 rsa 加密呢!

提了這些方法說明保護使用者明碼密碼不是作不到,只是有點麻煩而已。

然而那些程式設計師真的只是怕麻煩才不想使用 hash 密碼嗎? 根本不懂的程式設計師,就不要講了,剩下沒用 hash 的,除了怕麻煩外,我猜還怕另一樣東西: debug 。

紀錄「使用者明碼」密碼的惟一好處就是能操作「使用者」所能看到的頁面。

試想一個場景,某天使用者打客服電話,詢問歷史訂單事宜,他一直抱怨看不到之前的一筆 Ubuntu NB 訂單,可是客服用後台管理系統查詢,卻明確地說明使用者真的有這筆訂單。那這問題要如何解決?

如果客服有使用者的帳密,他是不是自己登入系統,來到相同頁面觀看,就能了解到底是系統有 bug ,還是使用者不會操作。有可能問題只是出在「訂單分頁」不夠明確,使用者不知道要點到第二頁去觀看訂單。

讓客服知道明碼密碼以便可以看到與使用者相同介面的網頁是不得以的方法嗎? 不。我們有更安全的作法。

我們的作法是在客服後台,有一個轉移帳戶的頁面,讓他填入帳號(且不用輸入密碼)後可轉換成任一個使用者,我們再紀錄那一個客服曾轉換成誰,又作了什麼,這樣客服不用知道使用者的明碼密碼,也可以變成那一個使用者,而且我們也知道客服幹了什麼好事,所以客服可以在面臨無法排除的困難時才會丟 ticket 給我們,這不是三方皆喜:使用者安全、客服好作事、程式設計師省事。

那這架構怎麼作? 因為程式語言、框架百百種。我只說明觀念,請程式設計師們自行發揮,當然有問題歡迎發問,或覺得我的方法可以改進的,也歡迎指教。

認證系統多半是使用 Session 架構來確認連線的使用者身份為何? 其他用 cookie 或是 GET 連結的也差不多,都是把使用者識別 ID (可能是使用者帳號,也可能是臨時編號)藏在某個變數之中,讓程式在執行時,能找到一個 key 值去對應資料庫中的使用者。

所以我們只要在那個對應資料庫使用者的程式中,多加上一個判斷式,如果有另一個轉換識別 ID 時,就把原使用者識別 ID 換成這個轉換識別 ID 。

例如: 何阿蒙客服登入系統後,連線 request 的使用者識別 ID 為 hoamon ,當他設定好轉換帳號為 grace 後,連線的 request 物件多了一個 grace 的轉換識別 ID 。這樣「對應資料庫使用者的程式」在運行時,就會知道使用者得用 grace 去代換,而不是 hoamon 。而我們的 log 函式在發現 request 物件多了轉換識別 ID 後,也會把『 hoamon => grace 』及所作的事一起紀錄到資料庫中。

這樣就能完全排除「明碼密碼」的使用了。

十一月 22, 2009

hoamon's sandbox
hoamon
hoamon's sandbox is about »

tag cloud

» 專案程式碼不得不兩線並進時, Mercurial 的簡單因應策略為何?

最近,我們的系統要作二周的使用者教育訓練,且接受他們的回饋意見,而系統功能離真正的完工還有一段小距離,因為他們可能會提出一些新的想法,若可行性高的話,我們也會把功能實作上去。

而這種「兩線並進」的程式碼維護該如何處理? 因為我們使用的是分散式版本控制器,所以這策略可分簡單及進階方法兩種,當然啦,進階方法必定有優點比簡單方法多一點,要不然,大家都用簡單方法不就得了。

首先,我們要先了解為什麼會有「兩線並進」的現象發生。

在作系統展示及教育訓練的時候,有可能會面臨到第一次出現的 bug ,因為這時候所輸入的資料、操作流程會因使用者的真實需求而與我們開發者在測試階段有所不同,造成我們會有 debug 的需求。但在這二周之間,除了去作教育訓練的人外,其他沒去的開發者會繼續作其他功能的設計,那系統程式碼也會有因新增功能而產生的修改。

那如果兩者所新增、修改的程式碼都在同一個儲存庫中,那是不是一定會發生開發者寫的新功能變成教育訓練時的新 bug 呢! 我相信會的。

所以這時候,一定要用兩線各自獨立運作的方式,才會避免雙方互挖牆腳。

首先介紹簡單方法:

在展示主機上,先作 hg clone ,得到一個 xxx 專案資料夾,然後再作一次 hg clone xxx xxx-bugfix 。這時候,我們使用 xxx-bugfix 來作系統展示之用,如果有 bug 的話,也直接修改在這個 xxx-bugfix 專案中,並把這些修改 push 回到 xxx 之中,而在 xxx 之中,我們則是作新功能(從伺服器 pull -u 來的)及 fixed bug 的合併。合併後再整個 push 回程式碼伺服器上。這樣一來,訓練者所作的 bug fix 也可以讓開發者獲得,而開發者寫的新功能不會影響訓練者使用的展示系統。

以上方法的確可以滿足「兩線並進」的需求,然而它有一些麻煩的事要處理,當訓練者在作 bug fix 時,他要不是在展示主機上直接修改,要不然就是把展示主機的 xxx-bugfix 抓回自己的電腦來處理,改回後,再放回展示主機,這造成了另一個問題,如果訓練者有兩個以上,而他們同時要作 bug fix 呢! 又回到 copy 的時光了,要不然就是在展示主機上再搞一個程式碼伺服器讓 xxx-bugfix 可以變成多人合作的 debug 專案。

Mercurial 的分散式架構讓「兩線並進策略」變得非常簡單,但如果只用了這一招,這有點小看了 Mercurial 的強大。

下節我將介紹使用 branch, merge 指令實現「兩線並進策略」。

八月 12, 2007

hoamon's sandbox
hoamon
hoamon's sandbox is about »

tag cloud

» 高級 Subversion GUI: Eclipse

對滑鼠重度使用者來說,編寫 python 程式是需要一個稱手的 IDE 工具的,在這方面,我強烈建議使用 Eclipse ,原因是跨平台、開源及外掛多,所以你可以用它來寫 java, PHP, perl, python, ruby...,缺點只有一個,要學會 java 才能幫它加特殊功能,還好你想得到的,多半有人作了。

但對不在乎滑鼠的使用者來說, Eclipse 是有點麻煩的,在編寫文字上,方便性就不如 VIM 了,快速移動、大區塊剪貼、尋找 re 字串、自動補齊(需 VIM 外掛)等,用 VIM 是十分容易作到的,像是你要打個 SuperviseCase.objects.all() ,你只要 Sup.obj.all() 這樣就夠了。

所以我並不常用 Eclipse 來開發程式,大部份是用它來 Demo 程式碼給學弟妹看,因為他們都是用這一套的。

但是 GUI 工具有一個好處,比較程式碼差異及看 svn log 時很方便,只要是使用 svn 時,會用到 less 指令的,都適合用 Eclipse + subclipse 來作。雖然 subversion 也有其他 GUI 工具配合,但 Eclipse 牌子比較大,用戶也比較多。建議各位試試。

七月 30, 2007

hoamon's sandbox
hoamon
hoamon's sandbox is about »

tag cloud

» 考研究所時我還不會寫遞迴

中興營管的研究特色:用程式+管理數學來解決營建問題。

所以入學考試時,通常會考一題程式設計。而我那一年的考題是:「請把 1、2、3、4、5 的所有排列情形列出」。還好我大一計概被當,大四才重修,沒忘了什麼是 Fortran 及 PE2,於是寫這個程式對我來說好像不會太難。

但主要的問題是那時的我認為程式設計只有 for loop + if..else.. 而已,所以一個該用遞迴寫的問題,我該如何實作。還好數學幫了我,因為在相同個數的自然數子集合中,其子集合的積及和必屬惟一值的特性,讓我用 5 個迴圈把問題解決,程式如下(因為我已忘了 Fortran ,所以用 Python 作範例):

1 for i1 in xrange(1,6):
2 for i2 in xrange(1,6):
3 for i3 in xrange(1,6):
4 for i4 in xrange(1,6):
5 for i5 in xrange(1,6):
6 if i1*i2*i3*i4*i5 == 120 and (i1+i2+i3+i4+i5) == 15:
7 print '%d,%d,%d,%d,%d' % (i1, i2, i3, i4, i5)
這個程式或許談不上美感,但它讓我滿意未來的發展。能如願進入中興營管,而不是朝陽營管,學的不是 VB + 基因演算法,而是 VB + Matlab + Linux + PHP + Open Source + 管理數學。

而使用遞迴的方法如下:
 1 def Line(ori, level, res):
2 if level == 0:
3 print ', '.join(res)
4 return
5
6 for i in xrange(len(ori)):
7 res.insert(0, ori[i])
8 tmp = ori[:]
9 null = tmp.pop(i)
10 Line(tmp, level-1, res)
11 res.pop(0)
12
13 ori = ['1','2','3', '4', '5']
14
15 Line(ori, len(ori), [])

七月 2, 2007

hoamon's sandbox
hoamon
hoamon's sandbox is about »

tag cloud

» 到底誰會寫程式?

看到 Jserv 提到 傑出的女性自由軟體程序員 。讓我想到除了女性會寫程式之外,非資訊科系的學生也可以作到,只是我目前還沒看到非資訊科系的傑出程式設計師(但這是因為我看的人還不夠多)。

程式原意是規劃,規劃出問題的解決之道。只要你能思考,又懂一點數學(至少要加減乘除),那麼你就可以作規劃了。程式設計絕非「資訊相關」科系的獨門。

事實上,我就見過一些 「資訊科系」畢業的工程師程式設計能力不足,但這不是他們的錯,因為資科、資工、資管的學生本來就不一定學得會程式設計的,想想看,如果在高中的時候誤會了自己的興趣及專長,數學不好但卻靠國文、英文考上資訊相關科系,那麼在程式設計這部份是會多吃點虧的。另一方面,資科、資 工、資管的學生也不一定會組電腦、設網路的,不要再強扣帽子在他們身上了,這好比大家也都認為土木系畢業的就一定會蓋房子一樣!

那麼對數學好的理工科學生來說,多半你己擁有程式設計的基本能力,只是待發揮而已。

那麼對理工科學生來說,為什麼一定要學會程式設計!理由我們可以從果蠅開始談起,如果你研究基因改變的原因,是在人身上著手,那麼窮其一生,你能作幾代 呢!大不了3代吧!如果是從果蠅下手呢!3天就1代,半年你就可以把數據整理好,拿來寫論文了。一樣地,作營建專案排程,如果不靠電腦,你就得靠手算,甚至得找一個工地真實模擬,那你得花多少時間呢;又或者一個機殼結構能承受多少真實外力?如果是要你先把機殼射出成型後再來測試,你又有多少時間寫論文。

現代電腦發展快速(這就是電機、電子、資訊相關科系學生的功榮了),很多現實問題的研究,我們可以利用電腦來完成。

程式的範圍太廣了,從低階的組合語言到高階的動態網頁,甚至還有應用在地震模擬、洋流模擬的程式,如果不懂背後的數學,又如果作規劃。

那麼理工科學生該學那種程式語言比較好呢!我的建議是至少學會 Python ,它什麼地方都可以用,寫系統管理、 GUI 程式、網頁程式還有它的數學函式庫支援豐富不下 Matlab ,它的資料結構簡單強大,不用學會如何配置記憶體就能上手。最重要的是它的難度適中,理工科常用的部份可以簡單學會。

biggo.com.tw

A Django site.