Web上的用戶登錄功能應(yīng)該是最基本的功能了纱意,可是在我看過(guò)一些站點(diǎn)的用戶登錄功能后团滥,我覺(jué)得很有必要寫(xiě)一篇文章教大家怎么來(lái)做用戶登錄功能竿屹。下面的文章告訴大家這個(gè)功能可能并沒(méi)有你所想像的那么簡(jiǎn)單,這是一個(gè)關(guān)系到用戶安全的功能灸姊,希望大家能從下面的文章中能知道什么樣的方法才是一個(gè)好的用戶登錄功能。
用戶名和口令
首先秉溉,我們先來(lái)說(shuō)說(shuō)用戶名和口令的事力惯。這并不是本站第一次談?wù)撨@個(gè)事了。如何管理自己的口令讓你知道怎么管理自己的口令召嘶,破解你的口令讓你知道在現(xiàn)代這樣速度的計(jì)算速度下父晶,用窮舉法破解你的口令可能會(huì)是一件很輕松的事。在這里我想告訴從開(kāi)發(fā)者的角度上來(lái)做設(shè)計(jì)這個(gè)用戶名和口令的事弄跌。下面一幾件規(guī)則:
限制用戶輸入一些非常容易被破解的口令甲喝。如什么qwert,123456, password之類(lèi)铛只,就像twitter限制用戶的口令一樣做一個(gè)口令的黑名單埠胖。另外糠溜,你可以限制用戶口令的長(zhǎng)度,是否有大小寫(xiě)直撤,是否有數(shù)字非竿,你可以用你的程序做一下校驗(yàn)。當(dāng)然谋竖,這可能會(huì)讓用戶感到很不爽红柱,所以,現(xiàn)在很多網(wǎng)站都提供了UX讓用戶知道他的口令強(qiáng)度是什么樣的(比如這個(gè)有趣的UX)蓖乘,這樣可以讓用戶有一個(gè)選擇锤悄,目的就是告訴用戶——要想安全,先把口令設(shè)得好一點(diǎn)嘉抒。
千萬(wàn)不要明文保存用戶的口令零聚。正如如何管理自己的口令所說(shuō)的一樣,很多時(shí)候众眨,用戶都會(huì)用相同的ID相同的口令來(lái)登錄很多網(wǎng)站握牧。所以,如果你的網(wǎng)站明文保存的話娩梨,那么沿腰,如果你的數(shù)據(jù)被你的不良員工流傳出去那對(duì)用戶是災(zāi)難性的。所以狈定,用戶的口令一定要加密保存颂龙,最好是用不可逆的加密,如MD5或是SHA1之類(lèi)的有hash算法的不可逆的加密算法纽什。CSDN曾明文保存過(guò)用戶的口令措嵌。(另,對(duì)于國(guó)內(nèi)公司的品行以及有關(guān)部門(mén)的管理方式芦缰,我不敢保證國(guó)內(nèi)網(wǎng)站以加密的方式保存你的口令企巢。我覺(jué)得,做為一個(gè)有良知的人让蕾,我們應(yīng)該加密保存用戶的口令)
是否讓瀏覽器保存口令浪规。我們有N多的方法可以不讓瀏覽器保存用戶名和口令。但是這可能對(duì)用戶來(lái)說(shuō)很不爽探孝。因?yàn)樵谡鎸?shí)世界里誰(shuí)也記得不住那么多的口令笋婿。很多用戶可能會(huì)使用一些密碼管理工具來(lái)保存密碼,瀏覽器只是其中一種顿颅。是否讓瀏覽器保存這個(gè)需要你做決定缸濒,重點(diǎn)是看一下你的系統(tǒng)的安全級(jí)別是否要求比較高,如果是的話,則不要讓瀏覽器保存密碼庇配,并在網(wǎng)站明顯的位置告訴用戶——保存口令最安全的地方只有你的大腦斩跌。
口令在網(wǎng)上的傳輸。因?yàn)镠TTP是明文協(xié)議讨永,所以滔驶,用戶名和口令在網(wǎng)上也是明文發(fā)送的,這個(gè)很不安全卿闹。你可以看看這篇文章你就明白了揭糕。要做到加密傳輸就必需使用HTTPS協(xié)議。但是锻霎,在中國(guó)還是有很多網(wǎng)站的Web登錄方式還在使用ActiveX控件著角,這可能成為IE6還大量存在的原因。我通常理解為這些ActiveX控件是為了反鍵盤(pán)記錄程序的旋恼。 不過(guò)吏口,我依然覺(jué)ActiveX控件不應(yīng)該存在,因?yàn)樵趪?guó)外的眾多安全很重要的站點(diǎn)上都看不到ActiveX的控件的身影冰更。
用戶登錄狀態(tài)
首先产徊,我想告訴大家的是,因?yàn)镠TTP是無(wú)狀態(tài)的協(xié)議蜀细,也就是說(shuō)舟铜,這個(gè)協(xié)議是無(wú)法記錄用戶訪問(wèn)狀態(tài)的,其每次請(qǐng)求都是獨(dú)立的無(wú)關(guān)聯(lián)的奠衔,一筆是一筆谆刨。而我們的網(wǎng)站都是設(shè)計(jì)成多個(gè)頁(yè)面的,所在頁(yè)面跳轉(zhuǎn)過(guò)程中我們需要知道用戶的狀態(tài)归斤,尤其是用戶登錄的狀態(tài)痊夭,這樣我們?cè)陧?yè)面跳轉(zhuǎn)后我們才知道是否可以讓用戶有權(quán)限來(lái)操作一些功能或是查看一些數(shù)據(jù)。
所以脏里,我們每個(gè)頁(yè)面都需要對(duì)用戶的身份進(jìn)行認(rèn)證她我。當(dāng)然,我們不可能讓用戶在每個(gè)頁(yè)面上輸入用戶名和口令迫横,這會(huì)讓用戶覺(jué)得我們的網(wǎng)站相當(dāng)?shù)腟B鸦难。為了實(shí)現(xiàn)這一功能,用得最多的技術(shù)就是瀏覽器的cookie员淫,我們會(huì)把用戶登錄的信息存放在客戶端的cookie里,這樣击敌,我們每個(gè)頁(yè)面都從這個(gè)cookie里獲得用戶是否登錄的信息介返,從而達(dá)到記錄狀態(tài),驗(yàn)證用戶的目的。但是圣蝎,你真的會(huì)用cookie嗎刃宵?下面是使用cookie的一些原則:
千萬(wàn)不要在cookie中存放用戶的密碼。加密的密碼都不行徘公。因?yàn)檫@個(gè)密碼可以被人獲取并嘗試離線窮舉牲证。所以,你一定不能把用戶的密碼保存在cookie中关面。我看到太多的站點(diǎn)這么干了坦袍。
正確設(shè)計(jì)“記住密碼”。這個(gè)功能簡(jiǎn)直就是一個(gè)安全隱患等太,我覺(jué)得并不是所有的程序員都知道怎么設(shè)計(jì)這個(gè)事捂齐。一般的設(shè)計(jì) 是——一時(shí)用戶勾選了這個(gè)功能,系統(tǒng)會(huì)生成一個(gè)cookie缩抡,cookie包括用戶名和一個(gè)固定的散列值奠宜,這個(gè)固定的散列值一直使用。這樣瞻想,你就可以在所有的設(shè)備和客戶上都可以登錄压真,而且可以有多個(gè)用戶同時(shí)登錄。這個(gè)并不是很安全蘑险。下面是一些更為安全的方法供你參考:
1)在cookie中滴肿,保存三個(gè)東西——用戶名,登錄序列漠其,登錄token嘴高。
用戶名:明文存放。
登錄序列:一個(gè)被MD5散列過(guò)的隨機(jī)數(shù)和屎,僅當(dāng)強(qiáng)制用戶輸入口令時(shí)更新(如:用戶修改了口令)拴驮。
登錄token:一個(gè)被MD5散列過(guò)的隨機(jī)數(shù),僅一個(gè)登錄session內(nèi)有效柴信,新的登錄session會(huì)更新它套啤。
2)上述三個(gè)東西會(huì)存在服務(wù)器上,服務(wù)器的驗(yàn)證用戶需要驗(yàn)證客戶端cookie里的這三個(gè)事随常。
3)這樣的設(shè)計(jì)會(huì)有什么樣的效果潜沦,會(huì)有下面的效果,
a)登錄token是單實(shí)例登錄绪氛。意思就是一個(gè)用戶只能有一個(gè)登錄實(shí)例唆鸡。
b)登錄序列是用來(lái)做盜用行為檢測(cè)的。如果用戶的cookie被盜后枣察,盜用者使用這個(gè)cookie訪問(wèn)網(wǎng)站時(shí)争占,我們的系統(tǒng)是以為是合法用戶燃逻,然后更新"登錄token",而真正的用戶回來(lái)訪問(wèn)時(shí)臂痕,系統(tǒng)發(fā)現(xiàn)只有用戶名和“登錄序列”相同伯襟,但是"登錄token" 不對(duì),這樣的話握童,系統(tǒng)就知道姆怪,這個(gè)用戶可能出現(xiàn)了被盜用的情況,于是澡绩,系統(tǒng)可以清除并更改登錄序列和登錄token稽揭,這樣就可以令所有的cookie失效,并要求用戶輸入口令英古。并給警告用戶系統(tǒng)安全淀衣。
4)當(dāng)然,上述這樣的設(shè)計(jì)還是會(huì)有一些問(wèn)題召调,比如:同一用戶的不同設(shè)備登錄膨桥,甚至在同一個(gè)設(shè)備上使用不同的瀏覽器保登錄。一個(gè)設(shè)備會(huì)讓另一個(gè)設(shè)備的登錄token和登錄序列失效唠叛,從而讓其它設(shè)備和瀏覽器需要重新登錄只嚣,并會(huì)造成cookie被盜用的假象。所以艺沼,你在服務(wù)器服還需要考慮- IP 地址
a) 如果以口令方式登錄册舞,我們無(wú)需更新服務(wù)器的"登錄序列"和 "登錄token"(但需要更新cookie)。因?yàn)槲覀冋J(rèn)為口令只有真正的用戶知道障般。
b) 如果 IP相同 调鲸,那么,我們無(wú)需更新服務(wù)器的"登錄序列"和"登錄"(但需要更新cookie)挽荡。因?yàn)槲覀冋J(rèn)為是同一用戶有同一IP(當(dāng)然藐石,同一個(gè)局域網(wǎng)里也有同一IP,但我們認(rèn)為這個(gè)局域網(wǎng)是用戶可以控制的定拟。網(wǎng)吧內(nèi)并不推薦使用這一功能)于微。
c) 如果 (IP不同 && 沒(méi)有用口令登錄),那么青自,“登錄token” 就會(huì)在多個(gè)IP間發(fā)生變化(登錄token在兩個(gè)或多個(gè)ip間被來(lái)來(lái)回回的變換)株依,當(dāng)在一定時(shí)間內(nèi)達(dá)到一定次數(shù)后,系統(tǒng)才會(huì)真正覺(jué)得被盜用的可能性很高延窜,此時(shí)系統(tǒng)在后臺(tái)清除“登錄序列”和“登錄token“恋腕,讓Cookie失效,強(qiáng)制用戶輸入口令(或是要求用戶更改口令)逆瑞,以保證多臺(tái)設(shè)備上的cookie一致吗坚。不要讓cookie有權(quán)限訪問(wèn)所有的操作
否則就是XSS攻擊祈远,這個(gè)功能請(qǐng)參看新浪微博的XSS攻擊。下面的這些功能一定要用戶輸入口令:
1)修改口令商源。
2)修改電子郵件。(電子郵件通常用來(lái)找回用戶密碼谋减,最好通發(fā)郵件或是發(fā)手機(jī)短信的方式修改牡彻,或者干脆就不讓改一一用電子郵件做帳號(hào)名)
3)用戶的隱私信息。
4)用戶消費(fèi)功能出爹。權(quán)衡Cookie的過(guò)期時(shí)間
如果是永不過(guò)期庄吼,會(huì)有很不錯(cuò)的用戶體驗(yàn),但是這也會(huì)讓用戶很快就忘了登錄密碼严就。如果設(shè)置上過(guò)期期限总寻,比如2周,一個(gè)月梢为,那么可能會(huì)好一點(diǎn)渐行,但是2周和一個(gè)月后,用戶依然會(huì)忘了密碼铸董。尤其是用戶在一些公共電腦上祟印,如果保存了永久cookie的話,等于泄露了帳號(hào)粟害。所以蕴忆,對(duì)于cookie的過(guò)期時(shí)間我們還需要權(quán)衡。
找回口令的功能
找回口令的功能一定要提供悲幅。但是很多朋友并不知道怎么來(lái)設(shè)計(jì)這個(gè)功能套鹅。我們有很多找回口令的設(shè)計(jì),下面我逐個(gè)點(diǎn)評(píng)一下汰具。
千萬(wàn)不要使用安全問(wèn)答卓鹿。事實(shí)證明,這個(gè)環(huán)節(jié)很煩人郁副,而且用戶并不能很好的設(shè)置安全問(wèn)答减牺。什么,我的生日啊存谎,我母親的生日拔疚,等等。因?yàn)榻裉斓幕ヂ?lián)網(wǎng)和以前不一樣了既荚,因?yàn)镾NS稚失,今天的互聯(lián)比以前更真實(shí)了,我可以上facebook恰聘,開(kāi)心句各,人人網(wǎng)吸占,LinkedIn查到你的很多的真實(shí)的信息。通過(guò)這些信息我可以使用安全問(wèn)答來(lái)重設(shè)你的口令凿宾。 這里需要說(shuō)一下 Facebook矾屯,F(xiàn)acebook的安全問(wèn)答很強(qiáng)大,還要你通過(guò)照片認(rèn)人初厚,呵呵件蚕。
不要重置用戶的密碼。因?yàn)檫@有可能讓用戶的密碼遭到惡意攻擊产禾。當(dāng)然排作,你要發(fā)個(gè)郵件給用戶讓其確認(rèn),用戶點(diǎn)擊郵件中的一個(gè)鏈接亚情,你再重置妄痪。我并不推薦這樣的方法,因?yàn)橛脩粢话愣紩?huì)用筆記下來(lái)這個(gè)很難記的口令楞件,然后登錄系統(tǒng)衫生,因?yàn)榈卿浵到y(tǒng)時(shí)使用了“記住密碼”的功能,所以導(dǎo)致用戶不會(huì)去修改密碼履因,從而要么導(dǎo)到被寫(xiě)下來(lái)的密碼被人盜取障簿,要么又忘記了密碼。
好一點(diǎn)的做法——通過(guò)郵件自行重置栅迄。當(dāng)用戶申請(qǐng)找回口令功能的時(shí)候站故,系統(tǒng)生成一個(gè)MD5唯一的隨機(jī)字串(可通過(guò)UID+IP+timestamp+隨機(jī)數(shù)),放在數(shù)據(jù)庫(kù)中毅舆,然后設(shè)置上時(shí)限(比如1小時(shí)內(nèi))西篓,給用戶發(fā)一個(gè)郵件,這個(gè)連接中包含那個(gè)MD5的字串的鏈接憋活,用戶通過(guò)點(diǎn)擊那個(gè)鏈接來(lái)自己重新設(shè)置新的口令岂津。
更好一點(diǎn)的做法——多重認(rèn)證。比如:通過(guò)手機(jī)+郵件的方式讓用戶輸入驗(yàn)證碼悦即。手機(jī)+郵件可能還不把握吮成,因?yàn)槭謾C(jī)要能會(huì)丟了,而我的手機(jī)可以訪問(wèn)我的郵箱辜梳。所以粱甫,使用U盾,SecureID(一個(gè)會(huì)變化的6位數(shù)token)作瞄,或是通過(guò)人工的方式核實(shí)用戶身份茶宵。當(dāng)然,這主要看你的系統(tǒng)的安全級(jí)別了宗挥。
口令探測(cè)防守
使用驗(yàn)證碼乌庶。驗(yàn)證碼是后臺(tái)隨機(jī)產(chǎn)生的一個(gè)短暫的驗(yàn)證碼种蝶,這個(gè)驗(yàn)證碼一般是一個(gè)計(jì)算機(jī)很難識(shí)別的圖片。這樣就可以防止以程序的方式來(lái)嘗試用戶的口令瞒大。事實(shí)證明螃征,這是最簡(jiǎn)單也最有效的方式。當(dāng)然糠赦,總是讓用戶輸入那些肉眼都看不清的驗(yàn)證碼的用戶體驗(yàn)不好会傲,所以,可以折中一下拙泽。比如Google,當(dāng)他發(fā)現(xiàn)一個(gè)IP地址發(fā)出大量的搜索后裸燎,其會(huì)要求你輸入驗(yàn)證碼顾瞻。當(dāng)他發(fā)現(xiàn)同一個(gè)IP注冊(cè)了3個(gè)以上的gmail郵箱后,他需要給你發(fā)短信方式或是電話方式的驗(yàn)證碼德绿。
用戶口令失敗次數(shù)荷荤。調(diào)置口令失敗的上限,如果失敗過(guò)多移稳,則把帳號(hào)鎖了蕴纳,需要用戶以找回口令的方式來(lái)重新激活帳號(hào)。但是个粱,這個(gè)功能可能會(huì)被惡意人使用古毛。最好的方法是,增加其嘗試的時(shí)間成本(以前的這篇文章說(shuō)過(guò)一個(gè)增加時(shí)間成本的解密算法)都许。如稻薇,兩次口令嘗試的間隔是5秒鐘。三次以上錯(cuò)誤胶征,帳號(hào)被臨時(shí)鎖上30秒塞椎,5次以上帳號(hào)被鎖1分鐘,10次以上錯(cuò)誤帳號(hào)被鎖4小時(shí)……但是這會(huì)導(dǎo)致惡意用戶用腳本來(lái)攻擊睛低,所以最好再加上驗(yàn)證碼案狠,驗(yàn)證碼出錯(cuò)次數(shù)過(guò)多不禁止登錄而是禁lP。
系統(tǒng)全局防守钱雷。上述的防守只針對(duì)某一個(gè)別用戶骂铁。惡意者們深知這一點(diǎn),所以急波,他們一般會(huì)動(dòng)用“僵尸網(wǎng)絡(luò)”輪著嘗試一堆用戶的口令从铲,所以上述的那種方法可能還不夠好。我們需要在系統(tǒng)全局域上監(jiān)控所有的口令失敗的次數(shù)澄暮。當(dāng)然名段,這個(gè)需要我們平時(shí)沒(méi)有受到攻擊時(shí)的數(shù)據(jù)做為支持阱扬。比如你的系統(tǒng)绘沉,平均每天有5000次的口令錯(cuò)誤的事件砸彬,那么你可以認(rèn)為掏击,當(dāng)口令錯(cuò)誤大幅超過(guò)這個(gè)數(shù)后灌曙,而且時(shí)間相對(duì)集中晓淀,就說(shuō)明有黑客攻擊奸攻。這個(gè)時(shí)候你怎么辦准潭?一般最常見(jiàn)使用的方法是讓所有的用戶輸錯(cuò)口令后再次嘗試的時(shí)間成本增加她君。
最后静稻,再說(shuō)一下警没,關(guān)于用戶登錄,使用第三方的 OAuth 和 OpenID 也不失為一個(gè)很不錯(cuò)的選擇振湾。
參考文章
- OWASP Guide To Authentication
- Dos and Don’ts of Client Authentication on the Web (PDF)
- Charles Miller’s Persistent Login Cookie Best Practice
- Wikipedia: HTTP cookie
- Personal knowledge questions for fallback authentication: Security questions in the era of Facebook
文章內(nèi)容轉(zhuǎn)載自 酷 殼 – CoolShell.cn 杀迹,作者 陳皓 , 原文 鏈接