本文翻譯自Auth-Boss。 若是有翻譯的不恰當或不對的地方, 歡迎指出。php
成爲一個認證老司機, 瞭解網絡上不一樣的身份認證方法。html
本文檔的目的是記錄和編目Web上的身份驗證方法。
認證指的是建立一個系統的過程,用戶能夠經過該系統「登陸」在線服務,並授予對受保護資源的訪問權限。
如下引用可能更好地總結我想要解釋的內容:前端
客戶端認證涉及向Web上的服務器證實客戶端(或用戶)的身份。[1]python
我是一個自學成才的開發人員,熱愛開源技術,學習,指導和知識共享。git
我寫這篇指南,由於關於驗證這方面的信息很難直接找到。我決定戴上個人「研究帽「,作一些跑腿的工做。github
我寫做風格簡潔,會用到一些技術詞。web
免責聲明:本文檔不做爲包含全部認證方法的網絡的目錄;
本文檔也不旨在提供「最佳」認證方法。
沒人給錢賄賂我。
若是你想贊助我那更棒, 能夠用一些其它方式, 好比領養一隻小狗,或者幫助正在辛勞的人們。redis
引文:這些引文表示我引用的來源。
若是你想讓我收下連接/更好地引用個人來源(不只僅是一個連接到原始發佈),我能夠這樣作。
若是你想讓我更好的引用引文, 我固然願意,不過請先讓我知道<3。算法
遺漏,錯誤:
犯錯並不罕見,我並非安全方面的專家
若是你看到一些能夠改進的東西請PR,告訴我哪裏弄錯了,我能夠改進。
有關PR更多的信息,請查看CONTRIBUTIONS.md。數據庫
我將使用本文檔中的一個常見示例來講明在「客戶端」(用戶在其計算機前面)和「服務器」(後臺)上發生的狀況的登陸流程。
咱們的例子將會有一個想象的朋友:Beorn。
Beorn喜歡針織,常常去http://knittingworld.com購買用品。
Beorn在knittingworld有一個賬號,咱們將看到他登錄的例子。
在討論用於管理身份驗證的技術以前,如下是你不該該作的。
如下某些項目可能不直接與登陸/身份驗證/用戶註冊有關,但一般有用。
切勿將密碼存儲爲數據庫中的純文本。
不要寫本身的哈希算法(除非你真的很聰明)
不要寫本身的認證技術(再次,除非你真的很聰明)。
使用HTTPS。
一些忠告
咱們還發現許多網站設計本身的身份驗證機制,以提供更好的用戶體驗。
不幸的是,設計師和實現者一般沒有安全背景,所以不能很好地理解他們可使用的工具[2]
web驗證開發領域中有至關多的術語。
下面是一個術語列表,您將在下面看到。
這是一個大的概念。我只能簡單的解釋一下它的含義。
Web是圍繞HTTP構建的 - 它是用於在Web服務器和用戶之間通訊的協議。
您的瀏覽器被視爲HTTP客戶端,由於它向HTTP服務器發送請求。
你的客戶能夠作不少不一樣類型的請求, - 你可能據說過一些最流行的請求 - POST POST PUT和DELETE。
HTTP服務器向您的瀏覽器 - 客戶端發送響應。
這些響應就是資源。
資源能夠是(但不限於):HTML文件,圖像,文本,JSON等。
你能夠認爲資源是從服務器返回的「文件」。
關於此主題的其餘連接:
RFC2616 - 這是一個關於HTTP的文檔規範。
它被列爲過時,但也列出了取代它的文檔。
HTTPS是安全的HTTP。
它與SSL / TLS密切相關。
最初在互聯網上的支付交易很受歡迎,最近變得愈來愈廣泛。
您可能會認爲https是「在瀏覽器中顯示在個人網址左側的綠色文本」;
常常伴隨着鎖的圖標或相似的東西。
HTTPS是用TLS(或在過去的日子裏,SSL)封裝的HTTP,以保護瀏覽器和服務器之間的流量。
HTTPS會對與您的HTTP請求一塊兒發送的信息和發回的響應進行加密。
這在咱們開始談論身份驗證時尤爲重要!
來自維基百科:
HTTPS在不安全的網絡建立安全通道。
這確保了合理的保護免受竊聽者和中間人攻擊,只要使用足夠的密碼套件而且服務器證書被驗證和信任。
TLS和SSL是加密協議。
TLS和SSL加密您經過網絡發送的數據 - 它旨在防止人們「竊聽」或篡改您要發送的數據。
SSLv2和v3今天被視爲不安全(請參閱POODLE),所以大多數HTTPS是使用TLS 1.2完成的。
YouTube上有一些有用的視頻,有助於解釋這些複雜的問題,
這個視頻MIT opencourseware挺不錯的!
state
,stateful
,stateless
和piece of state
。
這些是術語,它們的定義不一樣。
在本文裏,「piece of state」或「stateful」描述了一塊存儲在內存中的數據。
HTTP請求一般被描述爲「stateless」。
當您訪問網站和登陸時,您正在傳遞一些信息以及您的HTTP請求, 用來標識您的身份。
不管你須要使用什麼身份驗證方法來識別本身,都必須「附加」到某個或另外一個HTTP請求,由於你不能簡單地將該狀態放在HTTP協議自己中 - 必須採起另外一種形式,能夠凌駕於HTTP協議之上(正如你會看到在本文檔的其他部分。)。
可能有點誇張... 我認爲這篇來自蘇格蘭的文章解釋的很不錯The Ins and Outs of Token Based Authentication。
因爲HTTP協議是無狀態的,這意味着若是咱們使用用戶名和密碼驗證用戶,那麼在下一個請求,咱們的應用程序將不知道咱們是誰。
咱們必須再次驗證。
Cookie是存儲在用戶瀏覽器上的小數據。
Cookie與HTTP相反,是有狀態的 - 這意味着儘管HTTP不能存儲用戶信息,可是cookie能夠。
網絡Cookie的常見示例:
Beorn訪問http://knittingworld.com爲他的下一個針織項目購買一些不錯的紗線和材料。
他登陸後向他的購物車添加了三件商品。忽然他聽到一聲砰!
並意識到他的微波爐裏還有一罐金槍魚。很差!
Beorn關閉了瀏覽器,當即忘記了他購物車裏的東西,跑去檢查微波爐。
罐頭金槍魚的醬汁已經灑在他家的地板上,Beorn回到他的電腦前,並從新訪問https://knittingworld.com ...想看看他以前加入購物車的商品還在不在。
Cookies。
有不一樣種類的Cookies。
有些Cookie會在您的瀏覽器中停留多天,而其餘Cookie會在您關閉瀏覽器後當即消失。
Cookie在過去(仍然是)認證中起到了很大的做用。
Web服務器一般使用認證cookie來肯定用戶是否登陸以及他們有權訪問哪些資源。
持久性cookie有時會帶來麻煩,由於它們能夠被廣告商用來記錄關於用戶的web習慣的信息。
另外一方面,它們一般用於保存用戶每次訪問站點時沒必要從新輸入其登陸憑證。
您能夠經過導航到您的(使用Chrome)開發者工具並打開網絡標籤查看與請求一塊兒發送的Cookie。
刷新頁面將顯示傳入資源的列表,您能夠選擇其中的一個。
滾動列表, 看看找獲得cookie不!
您也能夠在開發人員工具的[Application]標籤中查看Cookie 的相關信息。
我並不會一開始就去嘗試簡單的描繪出sessions,我會引用OWASP:
網絡會話是與同一用戶相關聯的網絡HTTP請求和響應事務的序列。
現代和複雜的web應用程序須要在多個請求期間保留關於每一個用戶的信息或狀態。
所以,會話提供了創建變量的能力,例如訪問權限和本地化設置,這將適用於在會話期間用戶與webApp的每一次交互。
您能夠在下面的「Methodologies」部分找到基於會話身份驗證的示例。
關於Sessions的更多連接:
如下是用於創建認證的技術方案列表。這不是一個完整的列表!
HTTP基自己份驗證(或「基自己份驗證」)已經存在了很長時間。看起來人們傾向於使用它,由於它的簡單性,它支持跨瀏覽器。這是一個空白頁面,要求基本的驗證。這裏將演示如何確保webApp正常運行當Beorn關閉遊覽器從新再打開後:
Beorn去http://knittingworld.com 買紗線。
在挑選出紗線後,他點擊「購買」按鈕購買。
他的瀏覽器發出一個GET請求,服務器響應401告訴他須要驗證。
Beorn在他的用戶名和密碼中輸入登陸表單。
在他點擊登錄後,他的瀏覽器會發起GET(POST)請求, 並在請求頭裏帶着Authorization。Authorization請求頭相似於這樣Authorization:QWxhZGRpbjpvcGVuIHNlc2FtZQ==
服務器繼續驗證身份驗證頭並肯定Beorn是否能夠能夠提交購買操做。瀏覽器會記住Authorization,以後的每一次遊覽器提交的請求,都會在請求頭裏加上Authorization:QWxhZGRpbjpvcGVuIHNlc2FtZQ==
, 直到遊覽器關閉。
上面的示例受權頭部看起來不像用戶名和密碼,可是這是由於它是base64編碼。它沒有加密。
若是使用HTTP基本認證,請使用HTTPS。若是使用HTTP,身份驗證憑據將做爲明文發送到服務器。這很差。用戶的用戶名和密碼經過線路僅做爲base64編碼文本發送 - 這對於解碼來講很簡單。經過使用HTTPS / TLS,您確保從客戶端發送到服務器的數據被加密。
HTTP基本驗證由遊覽器實現,今天不多使用。
基本驗證使用API的基本認證,當與令牌組合時,(稍後討論)只是一個受權報頭,是徹底合理的。它有額外的好處,不須要API客戶端維護一個額外的會話cookie,而且,由於大多數系統日誌查詢參數而不是標題,將不會被默認記錄。
基本驗證與Token組合的時候, 好處不少,好比不須要客戶端單獨維護一個cookie, 而且也不會被客戶端記錄。
Session認證已經存在了一段時間,而且日常用的比較多。基於session的身份驗證的關鍵是,用戶的登陸與服務器上的內存的一段狀態或key-value存儲(如Redis中)相關聯。
讓咱們看看咱們的朋友Beorn使用基於session的身份驗證的示例。
Beorn去http://knittingworld.com 買一些東西。
當Beorn登陸時,他將他的憑據發送到服務器。
當憑據到達服務器時,服務器以這種方式或另外一種方式須要檢查Beorn是不是其數據庫中的用戶。在這一點上,Beorn尚未登陸。
Beorn的憑據匹配成功,因此他能夠登陸。
Beorn須要一些東西來識別他對服務器的將來請求 - 特別是若是他想要購買東西(必須登錄才能買)。這就是認證session的思想。
如今服務器知道Beorn是誰,而且已經將他識別爲數據庫中的用戶,服務器將向他(或「返回」)發送一個cookie,這能夠將Beorn列爲在之後的請求中是已經登錄的用戶。
如今,Beorn已經驗證,並在他的瀏覽器上有一個session cookie(cookie的一種)。
當Beorn轉到頁面http://knittingworld.com/great_deals.html 他正在作另外一個HTTP請求 - 但此次,他的session cookie將放在HTTP請求頭裏發送到服務器。
服務器將根據與內存中Session信息匹配的cookie進行身份驗證(能夠用redis,memcache等數據庫來保存)
當Beorn從http://knittingworld.com 退出時,他在服務器(或Redis等)上的會話實例將過時,他的會話cookie也會過時。
基於令牌的認證已經變得更加廣泛最近隨着RESTful API的應用,單頁應用程序和微服務的興起。
token是一小塊數據。
利用基於Token的認證的認證系統意味着用戶向服務器發出的請求攜帶token以執行認證邏輯。當發出HTTP請求時, token是驗證用戶是否有資格訪問資源的憑證。
token認證是無狀態的,而基於session的認證意味着在您的服務器(或在Redis等)中的某個地方保存着狀態用以識別用戶。
Auth0的博客文章Cookies vs Tokens:The Definitive 描述了cookie和令牌之間的身份驗證流程的差異的:
1. 用戶輸入其登陸信息 2. 服務器驗證信息是否正確,並建立一個session,而後將其存儲在數據庫中 3. 具備sessionID的Cookie將放置在用戶瀏覽器中 4. 在後續請求中,會根據數據庫驗證sessionID,若是有效,則接受請求 5. 一旦用戶註銷應用程序,會話將在客戶端和服務器端都被銷燬
1. 用戶輸入其登陸信息 2. 服務器驗證信息是否正確,並返回已簽名的token 3. token儲在客戶端,最多見的是存儲在`local storage`中,但也能夠存儲在session存儲或cookie中 4. 以後的HTTP請求都將token添加到請求頭裏 5. 服務器解碼JWT,而且若是令牌有效,則接受請求 6. 一旦用戶註銷,令牌將在客戶端被銷燬,不須要與服務器進行交互一個關鍵是,令牌是無狀態的。後端服務器不須要保存令牌或當前session的記錄。
問錯人了,夥計。我只是告訴你存在這個驗證方式。我不會比較沒有意義的比較,我盡最大努力作到這一點。有關更多有趣的免責聲明,請訪問上面的免責聲明部分。令牌的類型一些常見的令牌包括JWT(下面討論),SWT(簡單網絡令牌)和SAML(安全斷言標記語言)
JWT表明「JSON Web Token」。 JWT是一種基於Token的認證。 JWT基於Web標準。如今JWT用的愈來愈多;JWT是Token認證的一種,因此說JWT基於Token的認證。再次,基於Token的認證的不一樣方法具備不一樣的優勢和缺點。所以,上面的基於令牌的認證部分中的不少信息適用於此。
來自JWT RFC 7519標準化的摘要說明:JSON Web Token(JWT)是一種緊湊的,URL安全的方式,表示要在雙方之間傳輸的聲明。
JSON Web令牌是一個字符串。它可能看起來像這樣:
eyJhbGciOIJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
上面的字符串是你在使用JWT執行身份驗證時可能看到的;它是在認證時從服務器返回的憑證。JWT通過驗證而且安全,由於它們使用私鑰進行「數字簽名」,並使用密鑰進行身份驗證。
JWT是一個自包含的數據塊。每一個JWT由payload
和signature
組成。當您的服務器建立token時,您還能夠爲token分配惟一的數據,能夠在前端使用。這能夠用於保存稍後進行其餘數據庫調用的須要。你仍然應該警戒在發送給客戶的令牌中發佈機密信息(好比說用戶密碼等等)。
def create_token(user): """Create a JWT token, set expiry, iat, etc""" payload = { 'sub': user.id, 'name': user.first_name, 'role_id': user.role_id, 'iat': datetime.utcnow(), 'exp': datetime.utcnow() + timedelta(days=1) } token = jwt.encode(payload, MY_SECRET_KEY_SHHH_DONT_TELL_ANYONE, algorithm='HS256') return token.decode('unicode_escape')
上面的鍵sub,iat和exp跟隨保留的JWT鍵,但我也添加了用戶的名稱和role_id。你將須要一個庫來編碼/解碼JWT令牌。 JWT.io列出了許多語言的庫。
OAuth是一種認證協議,容許用戶對沒有密碼的服務器執行認證。 OAuth存在不少版本 - OAuth 1.0,OAuth 1.0a和OAuth 2.0。
若是您曾使用Twitter,Google或Facebook賬戶登陸了某項服務,那麼您已使用OAuth。
、
OAuth提供商(Facebook,Google等)經過提供您的服務(「OAuth客戶端」)身份驗證方式的私有,惟一的訪問令牌,容許登陸。
若是您要使用OAuth讓用戶登陸您的服務,則須要將您的服務器註冊爲OAuth客戶端。這一般會設置一個客戶端ID和客戶端密鑰。登陸到您的服務的用戶將重定位到OAuth提供程序,用戶能夠在其中確認他們確實想要「登陸」(即容許他們登陸的服務器)訪問OAuth提供程序的任何須需的信息。 )在咱們的朋友Beorn的狀況下...
在咱們的朋友Beorn的狀況下...
Beorn去http://knittingworld.com 買東西。
Beorn決定使用他的Google賬戶登陸。
提示Beorn輸入他的google賬戶信息(若是他尚未登陸
輸入信息後,Google(或者其它的OAuth提供商)將提示他是否要使用他的Google賬戶登陸http://knittinggworld.com 。
接受後,Beorn被重定向到http://knittingworld.com 。
若是knittingworld須要訪問關於Beorn信息的資源,它能夠向資源服務器(經過OAuth提供者)請求訪問它們,只要它的token是有效的。
OWASP說:
建議使用OAuth 1.0a或OAuth 2.0,由於已發現第一個版本(OAuth1.0)容易受到session固定的影響。OAuth 2.0依靠HTTPS進行安全保障,目前OAuth的API(如Facebook,Google,Twitter和Microsoft)已經實現了。 OAuth1.0a很難使用,由於它須要使用用於數字簽名的加密庫。然而,因爲OAuth1.0a不依賴HTTPS來實現安全性,所以它更適合於更高風險的事務。
OpenId是另外一種不須要密碼的身份驗證協議(相似於OAuth)。 OpenId網站有一個很是簡潔明瞭的描述,在我看來:
OpenID容許您使用現有賬戶登陸多個網站,而無需建立新密碼。您能夠選擇將信息與您的OpenID相關聯,以便與您訪問的網站(例如姓名或電子郵件地址)共享。使用OpenID,您能夠控制與您訪問的網站共享的信息量。使用OpenID,您的密碼僅提供給您的身份提供商,而後該提供商會確認您訪問的網站的身份。除了您的提供商,沒有網站曾經看到您的密碼,所以您不須要擔憂一個不道德或不安全的網站危害您的身份。
雖然從2005年開始,最近(2014年-h),OpenId發佈了OpenId Connect,這是一種「基於OAuth 2.0系列規範的可互操做身份驗證協議」(源)
OpenId相似於OAuth,但有一些差別。相似地,OpenId依賴於與第三方(依賴方(您登陸的站點))交互以提供認證憑證的身份提供商。
不一樣的是,您可使用OAuth容許您登陸的網站可以訪問來自提供程序的數據。這聽起來可怕和混亂,但這裏有一個簡單的例子:
Beorn註冊爲twitter。他要推銷他編織的帽子
Beorn不知道follow誰,沒有人follow他。 Beorn悲傷的感受不重要。
Twitter提示Beorn使用OAuth鏈接他的Google賬戶,以便他能夠導入他的聯繫人到Twiiter。
Beorn follow了一羣人,包括來自他多年沒有見過的高中的老朋友
Beorn這樣作了,如今他正在不停地tweeting。
這裏是Stack Overflow的登陸頁面的圖片,它提供了許多不一樣的身份驗證方法:
1 - Dos and Don’ts of Client Authentication on the Web. Page 2.
2 - Dos and Don’ts of Client Authentication on the Web. Page 1.
http://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication
https://blog.codinghorror.com/youre-probably-storing-passwords-incorrectly/