1. 程式人生 > >認證 協議 JWT OAuth Session Cookie

認證 協議 JWT OAuth Session Cookie

cot ack 後端 tel 曾經 pin algo col 會話

本文翻譯自Auth-Boss。 如果有翻譯的不恰當或不對的地方, 歡迎指出。

成為一個認證老司機, 了解網絡上不同的身份認證方法。

本文檔的目的是記錄和編目Web上的身份驗證方法。
認證指的是創建一個系統的過程,用戶可以通過該系統“登錄”在線服務,並授予對受保護資源的訪問權限。
以下引用可能更好地總結我想要解釋的內容:

客戶端認證涉及向Web上的服務器證明客戶端(或用戶)的身份。[1]

How

我寫作風格簡潔,會用到一些技術詞。

免責聲明:本文檔不作為包含所有認證方法的網絡的目錄;
本文檔也不旨在提供“最佳”認證方法。
沒人給錢賄賂我。
如果你想贊助我那更棒, 可以用一些其它方式, 比如領養一只小狗,或者幫助正在辛勞的人們。

引文:這些引文表示我引用的來源。
如果你想讓我收下鏈接/更好地引用我的來源(不僅僅是一個鏈接到原始發布),我可以這樣做。
如果你想讓我更好的引用引文, 我當然願意,不過請先讓我知道<3。

遺漏,錯誤:
犯錯並不罕見,我並不是安全方面的專家
如果你看到一些可以改進的東西請PR,告訴我哪裏弄錯了,我可以改進。
有關PR更多的信息,請查看CONTRIBUTIONS.md。

假想案例

我將使用本文檔中的一個常見示例來說明在“客戶端”(用戶在其計算機前面)和“服務器”(後臺)上發生的情況的登錄流程。

我們的例子將會有一個想象的朋友:Beorn。
Beorn喜歡針織,經常去http://knittingworld.com購買用品。
Beorn在knittingworld有一個帳號,我們將看到他登陸的例子。

一般最佳做法

在討論用於管理身份驗證的技術之前,以下是你不應該做的。

以下某些項目可能不直接與登錄/身份驗證/用戶註冊有關,但通常有用。

  • 切勿將密碼存儲為數據庫中的純文本。

  • 不要寫自己的哈希算法(除非你真的很聰明)

  • 不要寫自己的認證技術(再次,除非你真的很聰明)。

  • 使用HTTPS。

一些忠告

我們還發現許多網站設計自己的身份驗證機制,以提供更好的用戶體驗。不幸的是,設計師和實現者通常沒有安全背景,因此不能很好地理解他們可以使用的工具[2]

術語

web驗證開發領域中有相當多的術語。下面是一個術語列表,您將在下面看到。

HTTP 超文本傳輸協議。

這是一個大的概念。我只能簡單的解釋一下它的含義。Web是圍繞HTTP構建的 - 它是用於在Web服務器和用戶之間通信的協議。

您的瀏覽器被視為HTTP客戶端,因為它向HTTP服務器發送請求。你的客戶可以做很多不同類型的請求, - 你可能聽說過一些最流行的請求 - POST POST PUT和DELETE。

HTTP服務器向您的瀏覽器 - 客戶端發送響應。
這些響應就是資源。
資源可以是(但不限於):HTML文件,圖像,文本,JSON等。
你可以認為資源是從服務器返回的“文件”。

關於此主題的其他鏈接:

  • HTTP Made Really Easy

  • RFC2616 - 這是一個關於HTTP的文檔規範。
    它被列為過期,但也列出了取代它的文檔。

HTTPS

HTTPS是安全的HTTP。
它與SSL / TLS密切相關。
最初在互聯網上的支付交易很受歡迎,最近變得越來越普遍。
您可能會認為https是“在瀏覽器中顯示在我的網址左側的綠色文本”;
經常伴隨著鎖的圖標或類似的東西。

HTTPS是用TLS(或在過去的日子裏,SSL)封裝的HTTP,以保護瀏覽器和服務器之間的流量。

HTTPS會對與您的HTTP請求一起發送的信息和發回的響應進行加密。這在我們開始談論身份驗證時尤其重要!

來自維基百科:

HTTPS在不安全的網絡創建安全通道。

這確保了合理的保護免受竊聽者和中間人攻擊,只要使用足夠的密碼套件並且服務器證書被驗證和信任。

TLS / SSL

TLS和SSL是加密協議。
TLS和SSL加密您通過網絡發送的數據 - 它旨在防止人們“竊聽”或篡改您要發送的數據。
SSLv2和v3今天被視為不安全(請參閱POODLE),因此大多數HTTPS是使用TLS 1.2完成的。
YouTube上有一些有用的視頻,有助於解釋這些復雜的問題,
這個視頻MIT opencourseware挺不錯的!

State

statestatefulstatelesspiece of state
這些是術語,它們的定義不同。
在本文裏,“piece of state”或“stateful”描述了一塊存儲在內存中的數據。

HTTP請求通常被描述為“stateless”。
當您訪問網站和登錄時,您正在傳遞一些信息以及您的HTTP請求, 用來標識您的身份。
無論你需要使用什麽身份驗證方法來識別自己,都必須“附加”到某個或另一個HTTP請求,因為你不能簡單地將該狀態放在HTTP協議本身中 - 必須采取另一種形式,可以淩駕於HTTP協議之上(正如你會看到在本文檔的其余部分。)。
可能有點誇張... 我認為這篇來自蘇格蘭的文章解釋的很不錯The Ins and Outs of Token Based Authentication。

由於HTTP協議是無狀態的,這意味著如果我們使用用戶名和密碼驗證用戶,那麽在下一個請求,我們的應用程序將不知道我們是誰。我們必須再次驗證。

Cookies

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 / Session Management

我並不會一開始就去嘗試簡單的描繪出sessions,我會引用OWASP:

網絡會話是與同一用戶相關聯的網絡HTTP請求和響應事務的序列。

現代和復雜的web應用程序需要在多個請求期間保留關於每個用戶的信息或狀態。因此,會話提供了建立變量的能力,例如訪問權限和本地化設置,這將適用於在會話期間用戶與webApp的每一次交互。

您可以在下面的“Methodologies”部分找到基於會話身份驗證的示例。關於Sessions的更多鏈接:

  • How does a web session work

  • What are web sessions?

Methodologies

以下是用於建立認證的技術方案列表。這不是一個完整的列表!

HTTP基本認證

HTTP基本身份驗證(或“基本身份驗證”)已經存在了很長時間。看起來人們傾向於使用它,因為它的簡單性,它支持跨瀏覽器。這是一個空白頁面,要求基本的驗證。這裏將演示如何確保webApp正常運行當Beorn關閉遊覽器重新再打開後:

  • Beorn去http://knittingworld.com 買紗線。

  • 在挑選出紗線後,他點擊“購買”按鈕購買。

  • 他的瀏覽器發出一個GET請求,服務器響應401告訴他需要驗證。

  • Beorn在他的用戶名和密碼中輸入登錄表單。

  • 在他點擊登陸後,他的瀏覽器會發起GET(POST)請求, 並在請求頭裏帶著Authorization。Authorization請求頭類似於這樣Authorization:QWxhZGRpbjpvcGVuIHNlc2FtZQ==

  • 服務器繼續驗證身份驗證頭並確定Beorn是否可以可以提交購買操作。瀏覽器會記住Authorization,之後的每一次遊覽器提交的請求,都會在請求頭裏加上Authorization:QWxhZGRpbjpvcGVuIHNlc2FtZQ==, 直到遊覽器關閉。

關於HTTP基本身份驗證的一些重要註意事項:

  • 上面的示例授權頭部看起來不像用戶名和密碼,但是這是因為它是base64編碼。它沒有加密。

  • 如果使用HTTP基本認證,請使用HTTPS。如果使用HTTP,身份驗證憑據將作為明文發送到服務器。這不好。用戶的用戶名和密碼通過線路僅作為base64編碼文本發送 - 這對於解碼來說很簡單。通過使用HTTPS / TLS,您確保從客戶端發送到服務器的數據被加密。

  • HTTP基本驗證由遊覽器實現,今天很少使用。

  • 基本驗證使用API??的基本認證,當與令牌組合時,(稍後討論)只是一個授權報頭,是完全合理的。它有額外的好處,不需要API客戶端維護一個額外的會話cookie,並且,因為大多數系統日誌查詢參數而不是標題,將不會被默認記錄。

  • 基本驗證與Token組合的時候, 好處很多,比如不需要客戶端單獨維護一個cookie, 並且也不會被客戶端記錄。

鏈接

  • Basic Authentication on OWASP

  • Why does stripe use HTTP basic auth with a token instead of the header

基於Session的認證

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也會過期。

基於Token的認證

基於令牌的認證已經變得更加普遍最近隨著RESTful API的應用,單頁應用程序和微服務的興起。

什麽是token?

token是一小塊數據。

利用基於Token的認證的認證系統意味著用戶向服務器發出的請求攜帶token以執行認證邏輯。當發出HTTP請求時, token是驗證用戶是否有資格訪問資源的憑證。

這與基於Cookie的身份驗證有何不同?

token認證是無狀態的,而基於session的認證意味著在您的服務器(或在Redis等)中的某個地方保存著狀態用以識別用戶。

Auth0的博客文章Cookies vs Tokens:The Definitive 描述了cookie和令牌之間的身份驗證流程的差別的:

基於session的認證流程:

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的記錄。

哇標記聽起來很酷。他們比基於session的身份驗證更好嗎?

問錯人了,夥計。我只是告訴你存在這個驗證方式。我不會比較沒有意義的比較,我盡最大努力做到這一點。有關更多有趣的免責聲明,請訪問上面的免責聲明部分。令牌的類型一些常見的令牌包括JWT(下面討論),SWT(簡單網絡令牌)和SAML(安全斷言標記語言)

鏈接

  • Token Based Authentication - Implemenation Demonstration - W3

  • What is token based Authentication - SO

  • Token Based Authentication Made Easy

  • The Ins and Outs of Token Based Authentication

  • Cookies vs Tokens: The Definitive Guide (opinionated)

JWT

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是一個自包含的數據塊。每個JWT由payloadsignature組成。當您的服務器創建token時,您還可以為token分配唯一的數據,可以在前端使用。這可以用於保存稍後進行其他數據庫調用的需要。你仍然應該警惕在發送給客戶的令牌中發布機密信息(比如說用戶密碼等等)。

在Python中創建JWT令牌的示例函數:

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列出了許多語言的庫。

鏈接

  • Introduction to JSON web tokens

  • JWT Debugger

OAuth

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來實現安全性,因此它更適合於更高風險的事務。

鏈接

  • A Fun explanation of OAuth involving Donuts

OpenId

OpenId是另一種不需要密碼的身份驗證協議(類似於OAuth)。 OpenId網站有一個非常簡潔明了的描述,在我看來:

OpenID允許您使用現有帳戶登錄多個網站,而無需創建新密碼。您可以選擇將信息與您的OpenID相關聯,以便與您訪問的網站(例如姓名或電子郵件地址)共享。使用OpenID,您可以控制與您訪問的網站共享的信息量。使用OpenID,您的密碼僅提供給您的身份提供商,然後該提供商會確認您訪問的網站的身份。除了您的提供商,沒有網站曾經看到您的密碼,因此您不需要擔心一個不道德或不安全的網站危害您的身份。

雖然從2005年開始,最近(2014年-h),OpenId發布了OpenId Connect,這是一種“基於OAuth 2.0系列規範的可互操作身份驗證協議”(源)

OpenId和OAuth有什麽區別?

OpenId類似於OAuth,但有一些差異。類似地,OpenId依賴於與第三方(依賴方(您登錄的站點))交互以提供認證憑證的身份提供商。

不同的是,您可以使用OAuth允許您登錄的網站能夠訪問來自提供程序的數據。這聽起來可怕和混亂,但這裏有一個簡單的例子:

    • Beorn註冊為twitter。他要推銷他編織的帽子

    • Beorn不知道follow誰,沒有人follow他。 Beorn悲傷的感覺不重要。

    • Twitter提示Beorn使用OAuth連接他的Google帳戶,以便他可以導入他的聯系人到Twiiter。

    • Beorn follow了一群人,包括來自他多年沒有見過的高中的老朋友

    • Beorn這樣做了,現在他正在不停地tweeting。

認證 協議 JWT OAuth Session Cookie