[譯]搭建賬戶系統

alloween發表於2017-09-08

搭建賬戶系統

Troy Hunt 近期發表了一篇題為『新時代的認證指南』的博文。文章對於「你的網站應該使用什麼樣的密碼規則」給予了很多實用的建議,而通過參考權威機構的建議總是有助於說服同事或老闆。

我在 Google 工作期間從事過的一個專案就是他們的統一賬戶系統(特別是反劫持)。大多數網站都會有一個登入系統,閱讀 Troy 的文章極大地啟發了我去建立這樣的一個系統,從而將那些建議應用其中。

1. 最好不要有

不管是什麼業務,進行使用者認證並不是你的主職,現代登入系統需要考慮的有很多,密碼只是一個開始。如果你成功建立了賬戶,最終還得考慮:

  • 找回密碼
  • 電子郵箱的認證
  • 賬戶登出,常常比你想象的要困難(見下文)
  • 密碼的強力保護
  • 基於簡訊、手機應用和硬體金鑰的雙因子驗證
  • 對賬戶劫持的保護(當攻擊者已經知道了正確密碼而使用者還沒有雙因子驗證時)
  • 使用者的地區、語言、姓名、個人頭像等的偏好
  • 對桌面和移動端的登入支援
  • 異常行為的通知
  • 只允許特定手機的登入

隨著大公司對使用者驗證意識的提高和攻擊者的攻擊能力的提升,一成不變的驗證技術已經不符合時代的變化。幸運的是,你現在可以將你的身份驗證環節外包給那些支援 OAuth 協議的公司。

Web 開發者常常會在建立完自己的賬戶系統之後,才覺得新增『使用 Facebook 登入』『使用 Google 登入』是個不錯的方案。如果你是為了建立一個全新的網站而閱讀這篇文章,我建議『使用第三方登入』應該成為你的網站的唯一選項。如今,建立自己的賬戶系統就像是建立自己的資料中心,而不是使用 AWS。

人們有時候會擔心,如果只提供『第三方登入』按鈕用來登入,那麼那些大型的 ID 提供商可能會試圖竊取他們的客戶。通常情況下,人們擔心的情況是,使用 ID 提供商登入,但是卻被要求設定密碼。其實不用擔心這一點,這種情況不太可能發生,就算真的發生了,你也隨時可以通過電子郵件給他們傳送一個連結將你的客戶群遷移到你自己的系統上。

2. 使用郵箱或電話號碼來識別使用者

不要強制使用者設定使用者名稱,即使你的業務體驗是基於使用者名稱的,比如聊天論壇之類的。使用者通常是通過郵箱或者是電話抑或是兩者同時驗證的,如果你想讓每個使用者都擁有一個獨一無二的使用者名稱(用來展示的),那應該單獨選擇,為什麼呢?

  • 無論如何你都是要使用者提供郵箱地址的
  • 如果使用者名稱成為你的系統的個人識別符,你要考慮使用者是會隨時更改它的
  • 使用者經常會忘記使用者名稱,可一般不會忘記郵箱或電話號碼
  • 挑選使用者名稱的過程常常是讓人沮喪,一旦使用者使用了一個使用者名稱,卻因為該使用者名稱已經存在而不能通過時,有些人就會放棄了,從而你就流失了一位使用者
  • 將使用者名稱和用來展示的名字分開可以大大減少對使用者設定的限制,例如禁止空格

3. 完全放棄密碼

如果你還沒準備好將賬戶系統完全依賴於第三方 ID 提供商,那麼千萬不要設定密碼,這樣對每個人都有好處。

這個主意並不像它聽起來那麼愚蠢。你已經向使用者詢問他們的電子郵箱了,你所應該在你的登入系統上新增的第一個功能就是使用者忘記密碼後該如何恢復,你可以通過電子郵件給使用者傳送一個可點選的連結。這樣,只要使用者能夠使用該郵箱就能夠登入你的系統,而你的網站密碼也用不著增加額外的安全性。

我們跳過這一步,直接進入下一步,取而代之的——你的登入系統可以變得更簡單,只需通過郵件向使用者傳送一封包含了登入cookie的連結,使用者只需點選連結便能登入。Medium.com 便是如此

通過這種方法,只要使用者的裝置裝有電子郵件客戶端,就能夠登入。對於桌上型電腦、膝上型電腦、手機和平板來說也是如此。對於遊戲機和電視來說可能行不通,不過你的目標使用者可能不是這些人群。其中的匹配過程最好用藍芽的方式,因為這些裝置沒有方便使用的鍵盤。

過去常常有這樣的說法:缺少密碼輸入框會使使用者感到不自在。而現代的谷歌登入體驗正是如此,他們僅僅要求使用者輸入他們的電子郵箱地址,所以使用者並不會感到有什麼不自在,而且這麼做還大有好處。

而這種方法還有個好處:有些人只有電話號碼而沒有電子郵箱。在發展中國家尤其如此,所以如果這些國家的使用者是你的網站的潛在目標市場的話,最終你可能要支援僅能通過手機接受驗證碼的方式登入。這樣的賬戶根本就不需要密碼,如果你所有的使用者都有密碼,那麼你需要返回併為安全敏感的程式碼路徑新增許多特殊的情況(這很容易導致致命的錯誤)。

4. 不要使用密保問題

如果你就是想使用密碼——大概你懶得向你的老闆解釋為什麼你這麼特立獨行,那麼請至少不要讓使用者通過密保問題來找回他們的密碼。

  • 密保問題常常被猜測。使用者很難想出那些只有他們知道而其他人答不出來的問題。
  • 預設的問題使得猜測的現象更加嚴重
  • 預設問題往往帶有文化差異,從而使得它們對於許多使用者並不友好(例如:『你們高中學校的吉祥物是什麼?』)。
  • 一些『精明』的使用者意識到他們不能想出一個難以猜測的答案,所以僅僅在這個位置填入密碼,導致了他們在忘記密碼時無法恢復。
  • 還有一堆的高階黑客,會在密碼恢復流程上做點文章,你可不希望這事發生在你身上吧。

Google 曾經在密保問題上遇到過嚴重的問題。這是我的幾位老同事發表的研究,值得一看(視訊在下面,來自 youtube,需要翻牆)。

一場在谷歌進行的關於密保問題和答案的談話

這是一些問答的例子:

  • 問:你最喜歡的食物是?答:披薩。答案常常是披薩。僅僅通過猜出這個問題的答案,你就能破解大約 20% 的說英語的使用者。再新增十個猜測選項,你就能破解三分之一的設定了這個問題的使用者。而對於韓國使用者,你可以用 10 個以內的選項破解 43% 的使用者。
  • 問:你是在星期幾結的婚?答:星期四 是使用者自定義的問題,但卻有個致命的缺陷 —— 一般攻擊者只需要嘗試 5 次,就能破解正確答案。而這還不至於被檢測為暴力破解。
  • 問:我是在哪個城市出生的?答:首爾在一些國家裡,大多數人會聚居在少數的幾個大城市裡。觀察 ID 驗證使用者介面所使用的語言,可大大縮小可能的城市列表。通過這個問題,你能夠破解 40% 的使用者。
  • 問:我的第一位老師叫什麼名字?答:Mr Smith, Smith, John, John S. Smith,JOHN SMITH, Jon Smth。 這些都是正確答案,但是卻不能正確通過。我為這些問題提供了模糊匹配的模式,因為使用者的答案總是差那麼一點兒。匹配邏輯通常需要了解一些問題背景(『編輯距離』演算法本身不足以滿足諸如街道地址等的情況)。你還得讓你的產品支援多語言,祝你好運吧。

專業的賬戶系統是不會單獨使用密保問題來允許使用者恢復密碼的。它僅僅只是一種參考。我只給予你小於 2% 的機會去通過一個足夠複雜的機制來獲得這個權利。這就是為什麼 Google 逐步淘汰密保問題而採用簡訊的方式來恢復密碼。當然簡訊恢復自身也存在一些問題,但相比於密保問題還是好很多的。

5. 避免使用驗證碼

驗證碼是許多登入表單的常見功能。我在 Google 期間也做了一些相關的工作。但是,在如今驗證碼幾乎沒有什麼價值,而且執行率非常之低。

這些驗證碼都無濟於事。

首先要正確理解驗證碼的作用,它們僅僅對自動化攻擊施加非常簡單的限制。他們並不會保護你的賬戶系統免於批量註冊的風險。除了賬戶安全,我還花了幾年時間研究 Google 的註冊濫用。我們親眼看到垃圾郵件傳送者輕鬆地解決了數千萬個那些我們認為很難的驗證碼。有那些專業處理驗證碼的公司,如 DeathByCaptcha,他們使用的是光學字元識別和人工識別。普通的驗證碼讓盲人使用者無法進行註冊,這確實是個問題。而基於語音的驗證識別對於機器很容易,對人來說卻很困難。

使用驗證碼阻止暴力破解密碼是很有幫助的。暴力破解一個賬戶的密碼,可能需要成百上千次的嘗試,一個簡單的方法來阻止這種現象是在他們經過了幾次失敗的嘗試之後就開始加入驗證碼。在機械的迴圈中,即使是使用一個簡單的驗證碼來延緩程式也足夠了。

對於阻止批量賬戶註冊,驗證碼卻不太管用。建立一個系統去檢測和阻止這類現象是另一樁工作,在這方面我也花了好幾年的時間。你可以大致瞭解一下這有多困難,登入 buyaccs.com 並對比一下黑市賬戶銷售商收取的巨大差價。防禦系統較好的網站的賬戶通常會收取更高的價格。除非你是 Big 5 之一,不然在註冊安全方面,你所做的不可能超過我們,這也是我建議你將登入系統外包給那幾家主要的公司的另一個原因。

如果你仍然想要使用驗證碼,請使用 reCAPTCHA 並確保你的驗證碼放置在了適當的位置,以免重放攻擊。不要嘗試使用你自己製作的或是你在 GitHub 上找到的工具包,這樣的驗證碼很容易被現代的光學字元識別所解決,除了降低客戶註冊的成功率之外並沒有什麼用處。

6. 外包雙因子驗證

如今雙因子驗證是一個很常見的功能。然而,把它做好卻是很困難的,而且花費不菲,你不會想自己動手去實現它的。

  • 簡訊是不穩定的,特別是在有些國家,恢復碼常常不能顯示。你最終可能會選擇語音合成的電話,因為電話更加穩定一些,而現在你又需要考慮多語種的語音合成引擎了。
  • 大量的簡訊或電話將會是一筆大的開銷,即使你能通過大批量獲得優惠。
  • 人們可能常常會更換電話號碼。如果你的密碼恢復流程是基於電子郵件地址的,那麼這個過程將會變得很容易。但是一旦你的系統引入了穩定的雙因子認證,密碼恢復將變成你係統中的一個漏洞。如果你不去修復它,攻擊者將會很輕鬆地進行破解。而如果你嘗試阻止它也並不會起作用。
  • 雙因子驗證會被攻擊者濫用,他們將它新增到釣魚或者黑入的賬戶裡。這是為了在執行惡意活動期間,防止真正的使用者取回該賬號。
  • 電話號碼很容易受到移植攻擊,所以如今的趨勢是要求使用者設定移動應用或安全金鑰。為了實現這項措施意味著更多的工作,當然,這兩項可能都不管用,所以你最終還是需要一些客戶支援流程來幫助他們恢復。
  • 如你所見,雙因子驗證增加了大量客戶的手動操作,因為你不再使用密保問題或電子郵件的方式恢復使用者的密碼了。而這個開銷很大。

其中一些問題是很根本的,但是大多數已經有人幫你解決了,他們將免費為你支付電話費和客戶支援人員

不過,如果你仍然不想使用他們提供的服務,那麼還有一些創業公司可以為你解決小部分的雙因子驗證難題。

7. 不要強制使用者更改密碼

Troy 已經把這一點解釋的很好了,我這裡就不再贅述,但還要再強調一遍,這很重要。不要僅僅是因為使用者的密碼已經使用一段時間了,就讓使用者更改密碼。

  • 一些使用者可能無法通過這個流程,從而導致你流失一部分使用者。
  • 使用者可比你聰明,他們會更改密碼(一次、兩次、三次),然後立即將其更改為舊密碼,這意味著你得儲存最近密碼的歷史記錄以防止此類行為。但我敢打賭,你不會這樣做的。
  • 這樣並不會增加安全性。

8. 不要為會話設定有效期

是的,這又是個不好的『最佳實踐』。人們常常會為會話 cookie 設定有效期,覺得這樣做增加了安全性,出於同樣的原因,人們會認為為密碼設定有效期也會增加安全性。

  • 攻擊者往往會立即進行惡意活動,所以設定有效期並沒有多大用處。
  • 會話有效期這一設定使得使用者習慣於意料之外的密碼提示,這使得他們非常容易被欺騙。
  • 儲存有效期的隨機性會產生大量的 bug,導致了你的開發人員將大量的時間花在了修復 bug 上。你的網站的大部分程式碼應該不能處理這種,在一個操作中途,使用的會話過期了的情況,所以你必須返回去修復它,前提是你能夠發現的話。而由於使用者報告的隨機性,這使得追蹤錯誤變得更加困難了。

9. 記得登出

在不成熟的賬戶系統中,登出錯誤是非常常見的。這聽起來很簡單,但是實現這一功能的公認方法,是有缺陷的。

  • 簡單地刪除會話的 cookie 對使用者來說是方便的,但是這意味著你在遭受『跨站指令碼攻擊』後無法恢復。一旦發現『跨站指令碼攻擊』,你會希望,讓可能被盜取的會話 cookie 無效,但是如果登出只是『要求瀏覽器刪除 cookie』,那麼這樣做是不行的。
  • 將時間戳新增到會話 cookie,然後設定『最後登出時間』,每個操作都需要檢查帳戶資料庫,以瞭解使用者的會話是否過舊。這可能會導致操作響應變慢,意味著開發人員將要對此進行優化(畢竟這似乎也沒什麼)。但是如果他們移除了對攻擊者感興趣的一個埠的檢查,那麼你在第一步中遇到問題將會再次出現。另外,這意味著退出一個瀏覽器或裝置,就會將所有使用者登出,這不是預期的行為。

正確的方法是使用記憶體中快取來儲存過期會話 cookie 的列表。但是,對於大多數公司來說,有個成本更低而且足夠好的替代方案:讓使用者的退出連結僅僅當作是清除會話 cookie 的一種方式,緊接著可以讓會話 cookie 過期,並且每隔5分鐘自動更新。替換過期會話 cookie 的行為可以通過查詢資料庫,以檢視管理員是否強制登出了該賬戶。如果使用者顯示的是過期的 cookie,則需要重新登入。這就意味著 cookie 清理之後就不太可能被盜用了。

10. 從營銷郵件中分離帳號電子郵件

一般我們會用公司的主要電子郵箱伺服器來給使用者傳送恢復密碼連結、登入驗證等資訊。然而,貴公司的一些人卻會通過給使用者傳送那些他們不想收到的商業郵件與使用者建立『聯絡』。

即使使用者同意在帳號註冊期間收到這類資訊,但其中大部分使用者卻不想再收到這樣的資訊,有些人甚至會將其舉報為垃圾郵件。那些精明的使用者知道,這是一個極其方便的解決方案,僅僅簡單地點選『舉報垃圾郵件』,就能讓這些令人討厭的電子郵件消失,而不必把精力花費在尋找用微小字型寫著的『取消訂閱』連結,或是勞神費力地寫電子郵件過濾器。

而不幸的是,這類行為將會降低你的電子郵件域名的信譽。從你的帳戶系統傳送的郵件最終很可能會進入使用者的垃圾郵件資料夾。我們在註冊或進行密碼恢復的流程中,都能看到這類讓我們檢查垃圾郵件資料夾的提示 —— 就是這個原因。

解決這個問題的一種方法是,購買單獨的頂級域名來傳送郵件,並確保符合電子郵件驗證標準。但是,一些使用者可能會注意到域名不匹配,從而將你的電子郵件舉報為網路釣魚。最佳方案是使用不同電子郵件驗證標準的域名傳送你的營銷郵件,但你的產品人員可能不認可。所以,還是那句話,你選擇自己乾的那一刻,也同時承擔了痛苦。

11. 保護好你的密碼資料庫

一旦你擁有了密碼,你的資料庫就成了攻擊者的目標(而且他們常常能得手)。他們對你的公司並不感興趣,他們只是想要密碼,以方便他們嘗試那些更高價值目標。所以,資料洩露是個嚴重的問題,也許對客戶的直接影響沒那麼大,但有可能導致嚴重的後果。而使用 OAuth 協議的資料庫對於攻擊者來說卻沒什麼價值, 因此不太可能受到攻擊。

結論

關於帳戶系統我還能寫好多東西。保護你的網站,使其免受惡意帳戶入侵或註冊,這方面內容可以單獨寫成一本書了。這書我寫不了,不過如果你有興趣的話,可以看看這個視訊,這是我在 2012 年的一次訪談

老實說,這看似是一個浩大的工程,實則並非如此。所以我一直建議你要硬著頭皮堅持做下去,並且把你的賬戶管理外包給那些大公司。因為,你的主要業務並不是去操心怎樣擺弄驗證碼、不是怎樣寫『登出』的設計文件、不是診斷為什麼你會流失那些忘記密碼的使用者、也不是去考慮為什麼傳送資訊到祕魯會不穩定。你在這些事情上花費的每一分錢,對於那些提供了『使用第三方登入』的競爭對手來說,他們將這些錢都花在了他們的核心業務上。

所以,不要回頭看了,放棄你的密碼資料庫吧。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章