1. 程式人生 > >實現Web上的使用者登入功能

實現Web上的使用者登入功能

https://coolshell.cn/articles/5353.html

Web上的使用者登入功能應該是最基本的功能了,可是在我看過一些站點的使用者登入功能後,我覺得很有必要寫一篇文章教大家怎麼來做使用者登入功能。下面的文章告訴大家這個功能可能並沒有你所想像的那麼簡單,這是一個關係到使用者安全的功能,希望大家能從下面的文章中能知道什麼樣的方法才是一個好的使用者登入功能。以下內容,轉載時請保持原文一致,並請註明作者和出處

使用者名稱和口令

首先,我們先來說說使用者名稱和口令的事。這並不是本站第一次談論這個事了。如何管理自己的口令讓你知道怎麼管理自己的口令,破解你的口令讓你知道在現代這樣速度的計算速度下,用窮舉法破解你的口令可能會是一件很輕鬆的事。在這裡我想告訴從開發者的角度上來做設計這個使用者名稱和口令的事。下面一幾件規則:

  • 限制使用者輸入一些非常容易被破解的口令。如什麼qwert,123456, password之類,就像twitter限制使用者的口令一樣做一個口令的黑名單。另外,你可以限制使用者口令的長度,是否有大小寫,是否有數字,你可以用你的程式做一下校驗。當然,這可能會讓使用者感到很不爽,所以,現在很多網站都提供了UX讓使用者知道他的口令強度是什麼樣的(比如這個有趣的UX),這樣可以讓使用者有一個選擇,目的就是告訴使用者——要想安全,先把口令設得好一點。
  • 千萬不要明文儲存使用者的口令。正如如何管理自己的口令所說的一樣,很多時候,使用者都會用相同的ID相同的口令來登入很多網站。所以,如果你的網站明文儲存的話,那麼,如果你的資料被你的不良員工流傳出去那對使用者是災難性的。所以,使用者的口令一定要加密儲存,最好是用不可逆的加密,如MD5或是SHA1之類的有hash演算法的不可逆的加密演算法。CSDN曾明文儲存過使用者的口令。(另,對於國內公司的品行以及有關部門的管理方式,我不敢保證國內網站以加密的方式儲存你的口令。我覺得,做為一個有良知的人,我們應該加密儲存使用者的口令)
  • 是否讓瀏覽器儲存口令。我們有N多的方法可以不讓瀏覽器儲存使用者名稱和口令。但是這可能對使用者來說很不爽。因為在真實世界裡誰也記得不住那麼多的口令。很多使用者可能會使用一些密碼管理工具來儲存密碼,瀏覽器只是其中一種。是否讓瀏覽器儲存這個需要你做決定,重點是看一下你的系統的安全級別是否要求比較高,如果是的話,則不要讓瀏覽器儲存密碼,並在網站明顯的位置告訴使用者——儲存口令最安全的地方只有你的大腦。
  • 口令在網上的傳輸。因為HTTP是明文協議,所以,使用者名稱和口令在網上也是明文傳送的,這個很不安全。你可以看看這篇文章你就明白了。要做到加密傳輸就必需使用HTTPS協議。但是,在中國還是有很多網站的Web登入方式還在使用ActiveX控制元件,這可能成為IE6還大量存在的原因。我通常理解為這些ActiveX控制元件是為了反鍵盤記錄程式的。 不過,我依然覺ActiveX控制元件不應該存在,因為在國外的眾多安全很重要的站點上都看不到ActiveX的控制元件的身影。

使用者登入狀態

首先,我想告訴大家的是,因為HTTP是無狀態的協議,也就是說,這個協議是無法記錄使用者訪問狀態的,其每次請求都是獨立的無關聯的,一筆是一筆。而我們的網站都是設計成多個頁面的,所在頁面跳轉過程中我們需要知道使用者的狀態,尤其是使用者登入的狀態,這樣我們在頁面跳轉後我們才知道是否可以讓使用者有許可權來操作一些功能或是檢視一些資料。

所以,我們每個頁面都需要對使用者的身份進行認證。當然,我們不可能讓使用者在每個頁面上輸入使用者名稱和口令,這會讓使用者覺得我們的網站相當的SB。為了實現這一功能,用得最多的技術就是瀏覽器的cookie,我們會把使用者登入的資訊存放在客戶端的cookie裡,這樣,我們每個頁面都從這個cookie裡獲得使用者是否登入的資訊,從而達到記錄狀態,驗證使用者的目的。但是,你真的會用cookie嗎?下面是使用cookie的一些原則。

  • 千萬不要在cookie中存放使用者的密碼。加密的密碼都不行。因為這個密碼可以被人獲取並嘗試離線窮舉。所以,你一定不能把使用者的密碼儲存在cookie中。我看到太多的站點這麼幹了。
  • 正確設計“記住密碼”。這個功能簡直就是一個安全隱患,我覺得並不是所有的程式設計師都知道怎麼設計這個事。一般的設計 是——一時使用者勾選了這個功能,系統會生成一個cookie,cookie包括使用者名稱和一個固定的雜湊值,這個固定的雜湊值一直使用。這樣,你就可以在所有的裝置和客戶上都可以登入,而且可以有多個使用者同時登入。這個並不是很安全。下面是一些更為安全的方法供你參考:
    (——更新 2011/08/26,原文中有些小錯誤,並且說的不清楚,重新調整了一下——

1)在cookie中,儲存三個東西——使用者名稱登入序列登入token

使用者名稱:明文存放。
登入序列:一個被MD5雜湊過的隨機數,僅當強制使用者輸入口令時更新(如:使用者修改了口令)。
登入token:一個被MD5雜湊過的隨機數,僅一個登入session內有效,新的登入session會更新它。

2)上述三個東西會存在伺服器上,伺服器的驗證使用者需要驗證客戶端cookie裡的這三個事。

3)這樣的設計會有什麼樣的效果,會有下面的效果,

a)登入token是單例項登入。意思就是一個使用者只能有一個登入例項。

b)登入序列是用來做盜用行為檢測的。如果使用者的cookie被盜後,盜用者使用這個cookie訪問網站時,我們的系統是以為是合法使用者,然後更新“登入token”,而真正的使用者回來訪問時,系統發現只有“使用者名稱”和“登入序列”相同,但是“登入token” 不對,這樣的話,系統就知道,這個使用者可能出現了被盜用的情況,於是,系統可以清除並更改登入序列  登入token,這樣就可以令所有的cookie失效,並要求使用者輸入口令。並給警告使用者系統安全。

4)當然,上述這樣的設計還是會有一些問題,比如:同一使用者的不同裝置登入,甚至在同一個裝置上使用不同的瀏覽器保登入。一個裝置會讓另一個裝置的登入token登入序列失效,從而讓其它裝置和瀏覽器需要重新登入,並會造成cookie被盜用的假象。所以,你在伺服器服還需要考慮- IP 地址

a) 如果以口令方式登入,我們無需更新伺服器的“登入序列”和 “登入token”(但需要更新cookie)。因為我們認為口令只有真正的使用者知道。

b) 如果 IP相同 ,那麼,我們無需更新伺服器的“登入序列”和 “登入token”(但需要更新cookie)。因為我們認為是同一使用者有同一IP(當然,同一個局域網裡也有同一IP,但我們認為這個區域網是使用者可以控制的。網咖內並不推薦使用這一功能)。

c) 如果 (IP不同 && 沒有用口令登入),那麼,“登入token” 就會在多個IP間發生變化(登入token在兩個或多個ip間被來來回回的變換),當在一定時間內達到一定次數後,系統才會真正覺得被盜用的可能性很高,此時系統在後臺清除“登入序列”和“登入token“,讓Cookie失效,強制使用者輸入口令(或是要求使用者更改口令),以保證多臺裝置上的cookie一致。

  • 不要讓cookie有許可權訪問所有的操作。否則就是XSS攻擊,這個功能請參看新浪微博的XSS攻擊。下面的這些功能一定要使用者輸入口令:

1)修改口令。

2)修改電子郵件。(電子郵件通常用來找回使用者密碼,最好通發郵件或是發手機簡訊的方式修改,或者乾脆就不讓改一一用電子郵件做帳號名)

3)使用者的隱私資訊。

4)使用者消費功能。

  • 權衡Cookie的過期時間。如果是永不過期,會有很不錯的使用者體驗,但是這也會讓使用者很快就忘了登入密碼。如果設定上過期期限,比如2周,一個月,那麼可能會好一點,但是2周和一個月後,使用者依然會忘了密碼。尤其是使用者在一些公共電腦上,如果儲存了永久cookie的話,等於洩露了帳號。所以,對於cookie的過期時間我們還需要權衡。

找回口令的功能

找回口令的功能一定要提供。但是很多朋友並不知道怎麼來設計這個功能。我們有很多找回口令的設計,下面我逐個點評一下。

  • 千萬不要使用安全問答。事實證明,這個環節很煩人,而且使用者並不能很好的設定安全問答。什麼,我的生日啊,我母親的生日,等等。因為今天的網際網路和以前不一樣了,因為SNS,今天的互聯比以前更真實了,我可以上facebook,開心,人人網,LinkedIn查到你的很多的真實的資訊。通過這些資訊我可以使用安全問答來重設你的口令。 這裡需要說一下 Facebook,Facebook的安全問答很強大,還要你通過照片認人,呵呵。
  • 不要重置使用者的密碼。因為這有可能讓使用者的密碼遭到惡意攻擊。當然,你要發個郵件給使用者讓其確認,使用者點選郵件中的一個連結,你再重置。我並不推薦這樣的方法,因為使用者一般都會用筆記下來這個很難記的口令,然後登入系統,因為登入系統時使用了“記住密碼”的功能,所以導致使用者不會去修改密碼,從而要麼導到被寫下來的密碼被人盜取,要麼又忘記了密碼。
  • 好一點的做法——通過郵件自行重置。當用戶申請找回口令功能的時候,系統生成一個MD5唯一的隨機字串(可通過UID+IP+timestamp+隨機數),放在資料庫中,然後設定上時限(比如1小時內),給使用者發一個郵件,這個連線中包含那個MD5的字串的連結,使用者通過點選那個連結來自己重新設定新的口令。
  • 更好一點的做法——多重認證。比如:通過手機+郵件的方式讓使用者輸入驗證碼。手機+郵件可能還不把握,因為手機要能會丟了,而我的手機可以訪問我的郵箱。所以,使用U盾,SecureID(一個會變化的6位數token),或是通過人工的方式核實使用者身份。當然,這主要看你的系統的安全級別了。

口令探測防守

  • 使用驗證碼。驗證碼是後臺隨機產生的一個短暫的驗證碼,這個驗證碼一般是一個計算機很難識別的圖片。這樣就可以防止以程式的方式來嘗試使用者的口令。事實證明,這是最簡單也最有效的方式。當然,總是讓使用者輸入那些肉眼都看不清的驗證碼的使用者體驗不好,所以,可以折中一下。比如Google,當他發現一個IP地址發出大量的搜尋後,其會要求你輸入驗證碼。當他發現同一個IP註冊了3個以上的gmail郵箱後,他需要給你發簡訊方式或是電話方式的驗證碼。
  • 使用者口令失敗次數。調置口令失敗的上限,如果失敗過多,則把帳號鎖了,需要使用者以找回口令的方式來重新啟用帳號。但是,這個功能可能會被惡意人使用。最好的方法是,增加其嘗試的時間成本(以前的這篇文章說過一個增加時間成本的解密演算法)。如,兩次口令嘗試的間隔是5秒鐘。三次以上錯誤,帳號被臨時鎖上30秒,5次以上帳號被鎖1分鐘,10次以上錯誤帳號被鎖4小時……但是這會導致惡意使用者用指令碼來攻擊,所以最好再加上驗證碼,驗證碼出錯次數過多不禁止登入而是禁lP。
  • 系統全域性防守。上述的防守只針對某一個別使用者。惡意者們深知這一點,所以,他們一般會動用“僵屍網路”輪著嘗試一堆使用者的口令,所以上述的那種方法可能還不夠好。我們需要在系統全域性域上監控所有的口令失敗的次數。當然,這個需要我們平時沒有受到攻擊時的資料做為支援。比如你的系統,平均每天有5000次的口令錯誤的事件,那麼你可以認為,當口令錯誤大幅超過這個數後,而且時間相對集中,就說明有黑客攻擊。這個時候你怎麼辦?一般最常見使用的方法是讓所有的使用者輸錯口令後再次嘗試的時間成本增加。

最後,再說一下,關於使用者登入,使用第三方的 OAuth 和 OpenID 也不失為一個很不錯的選擇。

參考文章

以上內容,轉載時請保持原文一致,並請註明作者和出處