中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

高明網(wǎng)站建設(shè)最近一周新聞熱點回顧

高明網(wǎng)站建設(shè),最近一周新聞熱點回顧,寶安網(wǎng)站建設(shè)xbceo,做網(wǎng)站需要買服務(wù)器嗎本專欄將從基礎(chǔ)開始,循序漸進,以實戰(zhàn)為線索,逐步深入SpringSecurity相關(guān)知識相關(guān)知識,打造完整的SpringSecurity學(xué)習(xí)步驟,提升工程化編碼能力和思維能力,寫出高質(zhì)量代碼。希望大家都能夠從中有所收獲&#…

本專欄將從基礎(chǔ)開始,循序漸進,以實戰(zhàn)為線索,逐步深入SpringSecurity相關(guān)知識相關(guān)知識,打造完整的SpringSecurity學(xué)習(xí)步驟,提升工程化編碼能力和思維能力,寫出高質(zhì)量代碼。希望大家都能夠從中有所收獲,也請大家多多支持。
專欄地址:SpringSecurity專欄
本文涉及的代碼都已放在gitee上:gitee地址
如果文章知識點有錯誤的地方,請指正!大家一起學(xué)習(xí),一起進步。
專欄匯總:專欄匯總

文章目錄

    • 12.1 OAuth 2框架
    • 12.2 OAuth 2認(rèn)證架構(gòu)的組成部分
    • 12.3 OAuth 2的使用
      • 12.3.1 授權(quán)碼授予類型的使用
      • 12.3.2 密碼授予類型的使用
      • 12.3.3 客戶憑證授予類型的使用
      • 12.3.4 使用刷新token來獲得新的訪問token
    • 12.4 OAuth 2的缺點
    • 12.5 實現(xiàn)一個簡單的單點登錄應(yīng)用程序
      • 12.5.1 管理授權(quán)服務(wù)器
      • 12.5.2 開始實現(xiàn)
      • 12.5.3 實現(xiàn)客戶注冊
      • 12.5.4 實現(xiàn)ClientRegistrationRepository
      • 12.5.5 Spring Boot配置的魅力
      • 12.5.6 獲取已驗證用戶的詳細信息
      • 12.5.7 測試應(yīng)用程序

本章包括

  • OAuth 2的概述
  • OAuth 2規(guī)范的介紹
  • 建立一個使用單點登錄的OAuth 2應(yīng)用程序

如果你已經(jīng)在使用OAuth 2,我知道你在想什么:OAuth 2框架是一個龐大的主題,在四章中,你會學(xué)到所有你需要知道的關(guān)于用Spring Security應(yīng)用OAuth 2的知識。在這一章中,我們將從概述開始,你會發(fā)現(xiàn)OAuth 2框架的主要角色是用戶、客戶端、資源服務(wù)器和授權(quán)服務(wù)器。在總體介紹之后,你將學(xué)習(xí)如何使用Spring Security來實現(xiàn)客戶端。然后,在第13章到第15章,我們將討論實現(xiàn)最后兩個組件:資源服務(wù)器和授權(quán)服務(wù)器。

為了達到這個目標(biāo),在本章中,我們將討論什么是OAuth 2,然后我們將把它應(yīng)用于一個專注于單點登錄(SSO)的認(rèn)證的應(yīng)用。我之所以喜歡用SSO的例子來講授這個課題,是因為它非常簡單,但也非常有用。它提供了一個關(guān)于OAuth 2的概述,并讓你在不寫太多代碼的情況下實現(xiàn)一個完全有效的應(yīng)用程序,從而獲得滿足感。

在第13章到第15章中,我們將把本章所涉及的內(nèi)容應(yīng)用于你在本書前幾章中已經(jīng)熟悉的代碼實例中。一旦我們完成這四章,你就會對在你的應(yīng)用程序中用Spring Security實現(xiàn)OAuth 2所需要的東西有一個很好的概念。

由于OAuth 2是一個很大的主題,我將在適當(dāng)?shù)牡胤教岬轿艺J(rèn)為必要的知識。 Spring Security讓用OAuth 2開發(fā)應(yīng)用程序變得很容易。你需要開始的唯一先決條件是本書的第2章到第11章,在這些章節(jié)中你學(xué)到了Spring Security中認(rèn)證和授權(quán)的一般架構(gòu)。我們將討論的關(guān)于OAuth 2的內(nèi)容基于Spring Security的標(biāo)準(zhǔn)授權(quán)和認(rèn)證架構(gòu)。

12.1 OAuth 2框架

在本節(jié)中,我們將討論OAuth 2框架。今天,OAuth 2被普遍用于保障網(wǎng)絡(luò)應(yīng)用的安全,所以你可能已經(jīng)聽說過它了。你很有可能需要在你的應(yīng)用程序中應(yīng)用OAuth 2。這就是為什么我們需要討論在Spring應(yīng)用程序中使用Spring Security來應(yīng)用OAuth 2。我們從一點理論開始,然后在一個使用SSO的應(yīng)用程序中應(yīng)用它。

在大多數(shù)情況下,OAuth 2被稱為一個授權(quán)框架(或規(guī)范框架),其主要目的是允許第三方網(wǎng)站或應(yīng)用程序訪問資源。有時,人們把OAuth 2稱為一個委托協(xié)議。無論你選擇如何稱呼它,重要的是要記住,OAuth 2不是一個具體的實現(xiàn)或一個庫。你也可以用其他平臺、工具或語言來應(yīng)用OAuth 2的流程定義。在本書中,你會發(fā)現(xiàn)如何用Spring Boot和Spring Security實現(xiàn)OAuth 2。

我認(rèn)為理解OAuth 2是什么以及它的用處的一個好方法是用我們在本書中已經(jīng)分析過的例子開始討論。到目前為止,你在大量的例子中看到的最微不足道的認(rèn)證方式是HTTP Basic認(rèn)證方式。這對我們的系統(tǒng)來說還不夠,對于HTTP Basic認(rèn)證,我們有兩個問題需要考慮到:

  • 為每一個請求發(fā)送憑證(圖12.1)
  • 由一個單獨的系統(tǒng)管理用戶的憑證

image-20230129140416400

圖12.1 當(dāng)使用HTTP基本認(rèn)證時,你需要在所有請求中發(fā)送憑證并重復(fù)認(rèn)證邏輯。這種方法意味著經(jīng)常在網(wǎng)絡(luò)上分享憑證。

為每一個請求發(fā)送證書可能在個別情況下有效,但這通常是不可取的,因為它意味著

  • 經(jīng)常通過網(wǎng)絡(luò)共享憑證
  • 讓客戶(瀏覽器,在網(wǎng)絡(luò)應(yīng)用的情況下)以某種方式存儲證書,以便客戶可以將這些證書與請求一起發(fā)送給服務(wù)器,以獲得認(rèn)證和授權(quán)。

我們想從我們的應(yīng)用程序的架構(gòu)中擺脫這兩點,因為它們削弱了安全性。大多數(shù)情況下,我們希望有一個單獨的系統(tǒng)來管理用戶憑證。想象一下,你必須為你組織中的所有應(yīng)用程序配置和使用單獨的憑證(圖12.2)。

image-20230129140609634

圖12.2 在一個組織中,你與多個應(yīng)用程序一起工作。其中大部分都需要你進行認(rèn)證才能使用。對你來說,知道多個密碼是一種挑戰(zhàn),對組織來說,管理多套憑證也是一種挑戰(zhàn)。

如果我們把憑證管理的責(zé)任隔離在系統(tǒng)的一個組件中,那就更好了。我們暫且稱它為授權(quán)服務(wù)器(圖12.3)。

image-20230129140822548

圖12.3 一個更容易維護的架構(gòu)將憑證分開保存,并允許所有應(yīng)用程序為其用戶使用同一套憑證。

這種方法消除了代表同一個人的證書的重復(fù)性。通過這種方式,架構(gòu)變得更簡單,更容易維護。

12.2 OAuth 2認(rèn)證架構(gòu)的組成部分

在本節(jié)中,我們將討論在OAuth 2在認(rèn)證中發(fā)揮作用的組件。你需要了解這些組件和它們所扮演的角色,因為我們在接下來的章節(jié)中會提到它們。但在本節(jié)中,我們只討論這些組件是什么以及它們的用途(圖12.4)。正如你將在第12.3節(jié)中所了解的,這些組件之間有更多的交互方式。而且,在那一節(jié)中,你還會了解到導(dǎo)致這些組件之間不同交互的不同流程。

如前所述,OAuth 2組件包括

  • 資源服務(wù)器-托管用戶擁有的資源的應(yīng)用程序。 資源可以是用戶的數(shù)據(jù)或他們的授權(quán)行為。
  • 用戶(也被稱為資源所有者)–擁有資源服務(wù)器所提供的資源的個人。一個用戶通常有一個用戶名和密碼,用來識別自己。
  • 客戶端–代表用戶訪問其擁有的資源的應(yīng)用程序。
  • 授權(quán)服務(wù)器–授權(quán)客戶端訪問資源服務(wù)器所提供的用戶資源的應(yīng)用程序。當(dāng)授權(quán)服務(wù)器決定客戶端被授權(quán)代表用戶訪問某項資源時,它就會發(fā)出一個token??蛻舳耸褂眠@個token向資源服務(wù)器證明它是由授權(quán)服務(wù)器授權(quán)的。如果客戶端有一個有效的token,資源服務(wù)器就允許它訪問它所請求的資源。

image-20230129141603313

圖12.4 OAuth 2架構(gòu)的主要組成部分是資源所有者、客戶端、授權(quán)服務(wù)器和資源服務(wù)器。每一個都有自己的職責(zé),這在認(rèn)證和授權(quán)過程中是至關(guān)重要的。

12.3 OAuth 2的使用

在本節(jié)中,我們將討論如何應(yīng)用OAuth 2,這取決于你的應(yīng)用程序的架構(gòu)。正如你將了解到的,OAuth 2意味著多種可能的認(rèn)證流程,你需要知道哪一種適用于你的情況。在本節(jié)中,我將采取最常見的情況,并對這些情況進行評估。重要的是,在開始第一個實現(xiàn)之前,要先做這件事,以便你知道你在實現(xiàn)什么。

那么,OAuth 2是如何工作的?實現(xiàn)OAuth 2的認(rèn)證和授權(quán)是什么意思?簡而言之,OAuth 2是指使用token進行授權(quán)。 請記住11.2節(jié),token就像訪問卡。一旦你獲得一個token,你就可以訪問特定的資源。

但OAuth 2提供了多種獲得token的可能性,稱為授予。下面是最常見的OAuth 2授權(quán),你可以選擇。

  • 授權(quán)碼
  • 密碼
  • 刷新token
  • 客戶端憑證

12.3.1 授權(quán)碼授予類型的使用

在本節(jié)中,我們將討論授權(quán)碼授予類型(圖12.5)。我們還將在第12.5節(jié)中實現(xiàn)的應(yīng)用程序中使用它。該授予類型是最常用的OAuth 2流程之一,所以了解它的工作原理和如何應(yīng)用它是相當(dāng)重要的。你很有可能會在你開發(fā)的應(yīng)用程序中使用它。

image-20230129143415258

圖12.5 授權(quán)碼授予類型??蛻舳艘笥脩糁苯优c授權(quán)服務(wù)器交互,為用戶的請求授予許可。一旦獲得授權(quán),授權(quán)服務(wù)器就會發(fā)出一個token,客戶端使用該token來訪問用戶的資源。

圖12.5中的箭頭不一定代表HTTP請求和響應(yīng)。例如,當(dāng)客戶端告訴用戶(圖中頂部的第二個箭頭),“告訴授權(quán)服務(wù)器你允許我做這個動作”,客戶端就會把用戶重定向到授權(quán)服務(wù)器的登錄頁面。當(dāng)授權(quán)服務(wù)器給客戶端一個token時,授權(quán)服務(wù)器實際上是通過我們所說的重定向URI來調(diào)用客戶端。 你將在第12章到第15章中學(xué)習(xí)所有這些細節(jié),所以現(xiàn)在不用擔(dān)心。通過這個說明,我想讓你知道,這些順序圖并不只是代表HTTP請求和響應(yīng)。 這些是對OAuth 2行為體之間通信的簡化描述。

以下是授權(quán)碼授予類型的工作方式。在這之后,我們深入了解每個步驟的細節(jié)。

  1. 提出認(rèn)證請求
  2. 獲得一個訪問token
  3. 調(diào)用受保護的資源

第一步:用授權(quán)碼授予類型提出認(rèn)證請求

客戶端將用戶重定向到授權(quán)服務(wù)器的一個api,在那里他們需要進行認(rèn)證。你可以想象你正在使用應(yīng)用程序X,你需要訪問一個受保護的資源。為了訪問該資源,App X需要你進行身份驗證。 它為你打開一個頁面,在授權(quán)服務(wù)器上有一個登錄頁,你必須用你的證書來填寫。

從技術(shù)上講,這里發(fā)生的情況是,當(dāng)客戶端將用戶重定向到授權(quán)服務(wù)器時,客戶端調(diào)用授權(quán)端點,請求查詢中包含以下細節(jié):

  • response_type的值為code,它告訴授權(quán)服務(wù)器,客戶端希望有一個code??蛻舳诵枰@個code來獲得一個訪問token,你將在第二步中看到。
  • client_id,其值為客戶端ID,用于識別應(yīng)用程序本身。
  • redirect_uri,它告訴授權(quán)服務(wù)器在成功認(rèn)證后將用戶重定向到哪里。有時授權(quán)服務(wù)器已經(jīng)知道每個客戶的默認(rèn)重定向URI。由于這個原因,客戶端不需要發(fā)送重定向URI。
  • scope,這與我們在第五章中討論的授予權(quán)限相似。
  • state,其中定義了一個跨站請求偽造(CSRF)token,用于我們在第10章討論的CSRF保護。

認(rèn)證成功后,授權(quán)服務(wù)器重定向URI,并提供一個code和state。客戶端檢查state是否與它在請求中發(fā)送的state相同,以確認(rèn)它不是其他人在試圖調(diào)用重定向URI??蛻舳耸褂迷揷ode來獲得步驟2中提出的訪問token。

步驟2:獲得具有授權(quán)碼授予類型的訪問token

為了允許用戶訪問資源,步驟1產(chǎn)生的code是客戶端證明用戶認(rèn)證的證據(jù)。你猜得沒錯,這就是為什么這被稱為授權(quán)代碼授予類型?,F(xiàn)在,客戶端用code調(diào)用授權(quán)服務(wù)器以獲得token。

image-20230129145424009

圖12.6 第一步意味著用戶和授權(quán)服務(wù)器之間的直接互動。在這第二步中,客戶向授權(quán)服務(wù)器請求一個訪問token,并提供在第一步中獲得的授權(quán)碼。

在許多情況下,這前兩步會造成混亂。人們通常不明白為什么這個流程需要兩次調(diào)用授權(quán)服務(wù)器和兩個不同的token–授權(quán)碼和訪問token?;c時間來理解這一點。

  • 授權(quán)服務(wù)器生成第一個code,作為用戶直接與之互動的證明。客戶端收到這個code后,必須用它和它的憑證再次進行認(rèn)證,以獲得一個訪問token。
  • 客戶端使用第二個token來訪問資源服務(wù)器上的資源。

那么,為什么授權(quán)服務(wù)器沒有直接返回第二個token(訪問token)?嗯,OAuth 2定義了一個叫做隱式授予類型的流程,授權(quán)服務(wù)器直接返回一個訪問token。本節(jié)沒有列舉隱式授予類型,因為不建議使用這種類型,而且現(xiàn)在大多數(shù)授權(quán)服務(wù)器都不允許這樣做。授權(quán)服務(wù)器直接用訪問token調(diào)用重定向URI,而不確定它確實是接收該token的正確客戶端,這個簡單的事實使得流程的安全性降低。通過先發(fā)送一個授權(quán)碼,客戶必須通過使用他們的證書來獲得一個訪問token來再次證明他們是誰??蛻舳诉M行最后一次調(diào)用以獲得訪問token,并發(fā)送

  • 授權(quán)碼,證明用戶對其進行了授權(quán)
  • 他們的證書,這證明他們確實是同一個客戶,而不是其他截獲授權(quán)碼的人

回到第2步,從技術(shù)上講,客戶端現(xiàn)在向授權(quán)服務(wù)器提出了一個請求。這個請求包含以下細節(jié):

  • code,這是在步驟1中收到的授權(quán)代碼。這就證明了用戶的身份驗證。
  • client_id 和 client_secret 客戶的憑證。
  • redirect_uri 這與步驟1中的一樣。
  • grant_type grant_type對應(yīng)的值為authority_code,它標(biāo)識了所使用的流的種類。一個服務(wù)器可能支持多個認(rèn)證流,所以必須指定哪個是當(dāng)前執(zhí)行的認(rèn)證流。

作為響應(yīng),服務(wù)器會發(fā)回一個access_token。這個token是一個值,客戶可以用它來調(diào)用資源服務(wù)器所暴露的資源。

第3步:用授權(quán)碼授予類型調(diào)用受保護資源

在成功地從授權(quán)服務(wù)器獲得訪問token后,客戶端現(xiàn)在可以調(diào)用受保護的資源了??蛻舳嗽谡{(diào)用資源服務(wù)器的api時,在授權(quán)請求頭中使用訪問token。

在本節(jié)的最后,我用一個比喻來說明這種流動。我有時會從一家我認(rèn)識很久的小店買書。我必須提前訂書,然后在幾天后取書。但這家店不在我的日常上下班路線上,所以有時我不能自己去取書。我通常會請住在我附近的朋友去那里幫我取書。當(dāng)我的朋友詢問我的訂單時,商店的女士會打電話給我,確認(rèn)我已經(jīng)派人去取書了。在我確認(rèn)后,我的朋友就會去取包裹,并在當(dāng)天晚些時候把它帶給我。

在這個比喻中,書籍是資源。我擁有它們,所以我是用戶(資源所有者)。為我取書的朋友是client。賣書的女士是授權(quán)服務(wù)器。(我們也可以把她或書店看作是資源服務(wù)器。)請注意,為了授予我的朋友(客戶)取書(資源)的許可,賣書的女士(授權(quán)服務(wù)器)直接給我(用戶)打電話。這個類比描述了授權(quán)代碼和隱式授予類型的過程。當(dāng)然,由于我們在故事中沒有token,這個類比是局部的,描述了兩種情況。

授權(quán)碼授予類型有一個很大的優(yōu)點,就是使用戶能夠允許客戶端執(zhí)行特定的動作,而不需要與客戶端分享他們的憑證。但這種授予類型有一個弱點:如果有人攔截了授權(quán)代碼,會發(fā)生什么?當(dāng)然,客戶端需要用它的憑證進行驗證,正如我們之前討論的那樣。但是,如果客戶端的憑證也被盜了呢?即使這種情況不容易實現(xiàn),我們也可以認(rèn)為它是這種授予類型的漏洞。

12.3.2 密碼授予類型的使用

在本節(jié)中,我們討論密碼授予類型(圖12.7)。這種授予類型也被稱為資源所有者憑證授予類型。使用這種流程的應(yīng)用程序假定客戶端收集用戶憑證,并使用這些憑證來驗證和從授權(quán)服務(wù)器獲得訪問token。

還記得我們在第11章中的實戰(zhàn)例子嗎?我們實現(xiàn)的架構(gòu)與密碼授予類型中的情況非常接近。在第13章到第15章,我們還用Spring Security實現(xiàn)了一個真正的OAuth 2密碼授予類型架構(gòu)。

這時你可能會問,資源服務(wù)器是如何知道一個token是否有效的。在第13章和第14章,我們將討論資源服務(wù)器用來驗證token的方法。目前,你應(yīng)該把注意力集中在授予類型的討論上,因為我們只提到了授權(quán)服務(wù)器如何發(fā)放訪問token。

image-20230129151148384

圖12.7 密碼授予類型假定用戶與客戶端共享他們的憑證。 客戶端使用這些憑證從授權(quán)服務(wù)器獲得一個token。然后,它代表用戶從資源服務(wù)器上訪問資源。

只有當(dāng)客戶端和授權(quán)服務(wù)器是由同一個組織建立和維護時,你才會使用這個認(rèn)證流程。為什么呢?讓我們假設(shè)你建立了一個微服務(wù)系統(tǒng),你決定將認(rèn)證責(zé)任分離為一個不同的微服務(wù),以提高可擴展性并保持每個服務(wù)的責(zé)任分離。 這種分離在許多系統(tǒng)中被廣泛使用。

讓我們進一步假設(shè),你的系統(tǒng)的用戶使用的是一個用Angular、ReactJS或Vue.js等前端框架開發(fā)的客戶端Web應(yīng)用,或者他們使用的是一個移動應(yīng)用程序。在這種情況下,用戶可能會認(rèn)為從你的系統(tǒng)被重定向到同一個系統(tǒng)進行認(rèn)證,然后再返回是很奇怪的事情。這就是像授權(quán)碼授予類型的流程會發(fā)生的情況。對于密碼授予類型,你會期望應(yīng)用程序向用戶提供一個登錄表單,并讓客戶端負責(zé)向服務(wù)器發(fā)送憑證來進行認(rèn)證。用戶不需要知道你是如何在你的應(yīng)用程序中設(shè)計認(rèn)證責(zé)任的。讓我們看看在使用密碼授予類型時會發(fā)生什么。 這兩個任務(wù)如下。

  • 請求一個訪問token。
  • 使用訪問token來調(diào)用資源。

第1步:使用密碼授予類型時請求訪問token

密碼授予類型的流程要簡單得多??蛻舳耸占脩魬{證并調(diào)用授權(quán)服務(wù)器以獲得一個訪問token。當(dāng)請求獲得訪問token時,客戶端還在請求中發(fā)送以下細節(jié)。

  • grant_type,值為password
  • client_id 和 client_secret,是客戶用來認(rèn)證自己的憑證。
  • scope,它代表了被授予的權(quán)力
  • username 和password 是用戶憑證。這些是以純文本形式作為請求頭的值發(fā)送的。

客戶端在響應(yīng)中收到一個訪問token??蛻舳爽F(xiàn)在可以使用該訪問token來調(diào)用資源服務(wù)器的端點。

第2步:使用密碼授予類型時,使用訪問token來調(diào)用資源

一旦客戶端有了訪問token,它就會使用該token來調(diào)用資源服務(wù)器上的api,這與授權(quán)碼授予類型完全一樣??蛻舳藢⒃L問token添加到授權(quán)請求頭的請求中。

回到我在第12.3.1節(jié)所做的類比,想象一下,賣書的女士沒有給我打電話確認(rèn)我想讓我的朋友去拿書。我反而會把我的身份證給我的朋友,以證明我委托我的朋友去取書??吹絽^(qū)別了嗎?在這個流程中,我需要與客戶分享我的ID(憑證)。出于這個原因,我們說這種授予類型只適用于資源所有者 "信任 "客戶端的情況。

密碼授予類型不如授權(quán)碼授予類型安全,主要是因為它假定與客戶端應(yīng)用程序共享用戶憑證。雖然它確實比授權(quán)碼授予類型更直接,但在現(xiàn)實世界的場景中盡量避免這種授予類型。即使授權(quán)服務(wù)器和客戶端都是由同一個組織建立的,你也應(yīng)該首先考慮使用授權(quán)碼授予類型。 把密碼授予類型作為你的第二個選擇。

12.3.3 客戶憑證授予類型的使用

在本節(jié)中,我們將討論客戶憑證授予類型(圖12.8)。這是OAuth 2所描述的授予類型中最簡單的一種。我喜歡把客戶憑證授予類型看作是密碼授予類型和API密鑰認(rèn)證流程的結(jié)合。我們假設(shè)你有一個用OAuth 2實現(xiàn)認(rèn)證的系統(tǒng),現(xiàn)在你需要允許外部服務(wù)器進行認(rèn)證并調(diào)用你的服務(wù)器所暴露的特定資源。

image-20230129153751599

圖 12.8 客戶端憑證授予類型。如果客戶需要訪問一個資源,但不代表資源所有者,我們就使用這個流程。這個資源可以是一個不屬于用戶的api。

客戶憑證授予類型的步驟與密碼授予類型類似。唯一的例外是,訪問token的請求不需要任何用戶憑證。下面是實現(xiàn)這種授予類型的步驟:

  1. 請求一個訪問token
  2. 使用訪問token來調(diào)用資源

第1步:用客戶憑證授予類型請求訪問token

為了獲得一個訪問token,客戶端向授權(quán)服務(wù)器發(fā)送一個請求,并提供以下細節(jié)。

  • grant_type,值為client_credentials。
  • client_id和client_secret,代表客戶的證書。
  • scope,它代表了被授予的權(quán)力

作為響應(yīng),客戶端會收到一個訪問token。客戶端現(xiàn)在可以使用該訪問token來調(diào)用資源服務(wù)器的端點。

第2步:使用訪問token來調(diào)用具有客戶憑證授予類型的資源

一旦客戶端有了訪問token,它就會使用該token來調(diào)用資源服務(wù)器上的api,這與授權(quán)碼授予類型和通字授予類型完全一樣??蛻舳藢⒃L問token添加到授權(quán)請求頭中。

12.3.4 使用刷新token來獲得新的訪問token

在本節(jié)中,我們討論刷新token(圖12.9)。到目前為止,你已經(jīng)了解到,OAuth 2流程的結(jié)果,我們也稱之為授予,是一個訪問token。但我們并沒有對這個token說太多。最后,OAuth 2并沒有為token假設(shè)一個特定的實現(xiàn)。你現(xiàn)在要學(xué)習(xí)的是,無論如何實現(xiàn),token都會過期。這不是強制性的–你可以創(chuàng)建具有無限壽命的token–但是,一般來說,你應(yīng)該使這些token盡可能短命。我們在本節(jié)中討論的刷新token代表了一種獲得新訪問token的替代方法,即使用信用證。我向你展示了刷新token在OAuth 2中的工作原理,你還會在第13章看到這些token在一個應(yīng)用程序中的實現(xiàn)。

讓我們假設(shè)在你的應(yīng)用程序中,你實現(xiàn)了永不過期的token。這意味著客戶端可以反復(fù)使用同一個token來調(diào)用資源服務(wù)器上的資源。

如果token被盜怎么辦?最后,別忘了,token是作為一個簡單的HTTP頭附在每一個請求上的。如果token不會過期,拿到token的人就可以用它來訪問資源。一個不會過期的token是太強大了。它幾乎變得和用戶憑證一樣強大。我們傾向于避免這種情況,并使token的有效期短一些。這樣,在某些時候,過期的token就不能再使用了??蛻舳吮仨毇@得另一個訪問token。

為了獲得一個新的訪問token,客戶端可以重新運行流程,這取決于所使用的授予類型。例如,如果授予類型是認(rèn)證碼,客戶端會將用戶重定向到授權(quán)服務(wù)器的登錄api,用戶必須再次填寫他們的用戶名和密碼。這對用戶并不友好,不是嗎?想象一下,token有20分鐘的壽命,而你用在線應(yīng)用工作了幾個小時。在這段時間里,應(yīng)用程序會重定向你,讓你再次登錄。 了避免重新認(rèn)證的需要,授權(quán)服務(wù)器可以發(fā)出一個刷新token,它的價值和目的與訪問token不同。應(yīng)用程序使用刷新token獲得一個新的訪問token,而不需要重新認(rèn)證。

在密碼授予類型中,刷新token也比重新認(rèn)證有優(yōu)勢。即使是密碼授予類型,如果我們不使用刷新token,我們將不得不要求用戶再次認(rèn)證或存儲他們的憑證。在使用密碼授予類型時,存儲用戶憑證是你可能犯的最大錯誤之一。而且我已經(jīng)看到這種方法在實際應(yīng)用中的使用!請不要這樣做!如果你存儲了用戶名和密碼(假設(shè)你把這些保存為明文或可逆的東西,因為你必須能夠重復(fù)使用它們),你就暴露了這些憑證。刷新token可以幫助你輕松、安全地解決這個問題。你可以存儲一個刷新token,并在需要時使用它來獲得一個新的訪問token,而不是不安全地存儲憑證,也不需要每次都重定向用戶。存儲刷新token是比較安全的,因為如果你發(fā)現(xiàn)它被暴露,你可以撤銷它。此外,不要忘記,人們往往對多個應(yīng)用程序擁有相同的憑證。因此,丟失憑證比丟失一個可以在特定應(yīng)用中使用的token更糟糕。

最后,讓我們看看如何使用刷新token。你從哪里得到一個刷新token?當(dāng)使用像授權(quán)碼或密碼授予類型的流程時,授權(quán)服務(wù)器會將刷新token與訪問token一起返回。對于客戶憑證授予,沒有刷新token,因為這個流程不需要用戶憑證。一旦客戶端有了刷新token,當(dāng)訪問token過期時,客戶端應(yīng)該發(fā)出一個包含以下細節(jié)的請求:

  • grant_type的值為refresh_token。
  • refresh_token,其值為刷新token的值。
  • client_id和client_secret。
  • scope 其中定義了相同的授予權(quán)限或更少。如果需要授權(quán)更多的授予權(quán)限,則需要重新認(rèn)證。

作為對該請求的響應(yīng),授權(quán)服務(wù)器發(fā)出一個新的訪問token和一個新的刷新token。

12.4 OAuth 2的缺點

在本節(jié)中,我們將討論OAuth 2認(rèn)證和授權(quán)可能存在的漏洞。了解在使用OAuth 2時可能出現(xiàn)的問題是很重要的,這樣你就可以避免這些情況。當(dāng)然,就像軟件開發(fā)中的其他東西一樣,OAuth 2并不是無懈可擊的。它有自己的弱點,我們必須意識到這些弱點,并且在構(gòu)建我們的應(yīng)用程序時必須考慮這些弱點。我在這里列舉了一些最常見的。

  • 在客戶端使用跨站請求偽造(CSRF)–在用戶登錄的情況下,如果應(yīng)用程序沒有應(yīng)用任何CSRF保護機制,CSRF是可能發(fā)生的。我們在第10章中對Spring Security實現(xiàn)的CSRF保護進行了討論。
  • 竊取客戶憑證–存儲或轉(zhuǎn)移未受保護的憑證會產(chǎn)生漏洞,使攻擊者能夠竊取和使用這些憑證。
  • 重放token–正如你將在第13章和第14章中所學(xué)到的,token是我們在OAuth 2認(rèn)證和授權(quán)架構(gòu)中用來訪問資源的鑰匙。你通過網(wǎng)絡(luò)發(fā)送這些東西,但有時,它們可能會被截獲。如果被截獲,它們就會被盜,并可以被重新使用。想象一下,你丟失了你家前門的鑰匙??赡軙l(fā)生什么?其他人可以用它來打開門,只要他們愿意。我們將在第14章學(xué)習(xí)更多關(guān)于token的知識,以及如何避免token重放。
  • token劫持-暗示有人干擾認(rèn)證過程并竊取他們可以用來訪問資源的token。這也是使用刷新token的一個潛在漏洞,因為這些token也可以被攔截并用于獲得新的訪問token。

記住,OAuth 2是一個框架。漏洞是在它上面錯誤地實現(xiàn)功能的結(jié)果。使用Spring Security已經(jīng)可以幫助我們減輕應(yīng)用程序中的大部分漏洞。

12.5 實現(xiàn)一個簡單的單點登錄應(yīng)用程序

在本節(jié)中,我們將實現(xiàn)本書中第一個使用OAuth 2框架與Spring Boot和Spring Security的應(yīng)用。這個例子向你展示了如何用Spring Security應(yīng)用OAuth 2的總體概況。顧名思義,單點登錄(SSO)應(yīng)用是指你通過授權(quán)服務(wù)器進行認(rèn)證,然后應(yīng)用使用刷新token讓你保持登錄狀態(tài)。在我們的案例中,它只代表OAuth 2架構(gòu)中的client。

在這個應(yīng)用中(圖12.10),我們使用GitHub作為授權(quán)和資源服務(wù)器,并著重于組件之間的通信與授權(quán)代碼授予類型。在第13章和第14章中,我們將在一個OAuth 2架構(gòu)中同時實現(xiàn)授權(quán)服務(wù)器和資源服務(wù)器。

image-20230129160039276

圖 12.10 我們的應(yīng)用程序在 OAuth 2 架構(gòu)中扮演著客戶端的角色。我們使用GitHub作為授權(quán)服務(wù)器,但它也承擔(dān)了資源服務(wù)器的角色,這使我們能夠檢索到用戶的詳細信息。

12.5.1 管理授權(quán)服務(wù)器

在這一節(jié)中,我們將配置授權(quán)服務(wù)器。在本章中,我們不會實現(xiàn)我們自己的授權(quán)服務(wù)器,而是使用一個現(xiàn)有的服務(wù)器。GitHub。在第13章,你將學(xué)習(xí)如何實現(xiàn)自己的授權(quán)服務(wù)器。

那么,我們應(yīng)該如何使用像GitHub這樣的第三方作為授權(quán)服務(wù)器呢? 這意味著,最終我們的應(yīng)用程序不會管理其用戶,任何人都可以使用他們的GitHub賬戶登錄我們的應(yīng)用程序。就像其他授權(quán)服務(wù)器一樣,GitHub 需要知道它向哪個客戶端應(yīng)用程序發(fā)放token。 記得在第 12.3 節(jié)中,我們討論了 OAuth 2 的授予,請求使用了一個客戶端 ID 和一個客戶端密碼??蛻舳耸褂眠@些憑證在授權(quán)服務(wù)器上驗證自己,因此OAuth應(yīng)用程序必須在GitHub授權(quán)服務(wù)器上注冊。要做到這一點,我們要使用下面的鏈接完成一個簡短的表單提交(圖12.11)。

https://github.com/settings/applications/new

image-20230129160427566

圖 12.11 要把你的應(yīng)用程序作為 OAuth 2 客戶端,以 GitHub 作為授權(quán)服務(wù)器,你必須先注冊它。你可以通過填寫表格在 GitHub 上添加一個新的 OAuth 應(yīng)用程序來完成。

當(dāng)你添加一個新的OAuth應(yīng)用時,你需要為該應(yīng)用指定一個名稱,主頁,以及GitHub將對你的應(yīng)用進行回調(diào)的鏈接。與此相關(guān)的OAuth 2授予類型是授權(quán)碼授予類型。這種授予類型假定客戶端將用戶重定向到授權(quán)服務(wù)器(在我們的例子中是GitHub)進行登錄,然后授權(quán)服務(wù)器在定義的URL上回調(diào)客戶端,正如我們在12.3.1節(jié)所討論的那樣。這就是為什么你需要在這里確定回調(diào)URL的原因。因為我在自己的系統(tǒng)上運行這個例子,所以我在兩種情況下都使用localhost。而且因為我沒有改變端口(默認(rèn)是8080,你已經(jīng)知道了),這使得http://localhost:8080 我的主頁URL。我在回調(diào)中使用相同的URL。

一旦你填完表格并選擇注冊申請,GitHub 就會為你提供一個客戶端 ID 和一個客戶端密碼(圖 12.12)。

image-20230129160811209

圖 12.12 當(dāng)你在 GitHub 注冊一個 OAuth 應(yīng)用時,你會收到客戶端的憑證。你可以在你的應(yīng)用程序配置中使用這些證書。

15a2c5a0e3fe921a223d
43cfa8dea92894ed7c26ec1ced76ee9354e15e15

注意 我刪除了你在圖片中看到的應(yīng)用程序。因為這些證書提供了對機密信息的訪問,我不能讓它們繼續(xù)存在。由于這個原因,你不能重復(fù)使用這些憑證;你需要按照本節(jié)的要求生成你自己的憑證。另外,在使用這些憑證編寫應(yīng)用程序時要小心,尤其是在使用公共的 Git 倉庫來存儲這些憑證時。

這個配置是我們?yōu)槭跈?quán)服務(wù)器所需要做的一切?,F(xiàn)在我們有了客戶證書,我們就可以開始開發(fā)我們的應(yīng)用程序了。

12.5.2 開始實現(xiàn)

在本節(jié)中,我們開始實現(xiàn)一個SSO應(yīng)用。我們創(chuàng)建一個新的Spring Boot應(yīng)用程序,并在pom.xml文件中添加以下的依賴項。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

我們首先需要一個web頁面。為了做到這一點,我們創(chuàng)建了一個controller類和一個簡單的HTML頁面來代表我們的應(yīng)用程序。下面列出了MainController類,它定義了我們應(yīng)用程序的單一api。

代碼清單12.1 controller類

package com.hashnode.proj0001firstspringsecurity.controller;import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;import java.util.logging.Logger;@Controller
public class MainController {private Logger logger =Logger.getLogger(MainController.class.getName());@GetMapping("/")public String main(OAuth2AuthenticationToken token) {logger.info(String.valueOf(token));return "main.html";}
}

我還在我的Spring Boot項目的資源/靜態(tài)文件夾中定義了main.html頁面。它只包含標(biāo)題文本,以便我在訪問該頁面時可以觀察到以下情況:

Hello there!

現(xiàn)在是真正的工作!讓我們來設(shè)置安全配置,讓我們的應(yīng)用程序能夠使用GitHub的登錄方式。我們先寫一個配置類,就像我們習(xí)慣的那樣。 我們擴展WebSecurityConfigurerAdapter并重寫configure(HttpSecurity http)方法?,F(xiàn)在有一個不同之處:我們沒有像在第四章中學(xué)到的那樣使用httpBasic()或formLogin(),而是調(diào)用一個不同的方法,名為oauth2Login()。這段代碼在下面的代碼中呈現(xiàn)。

代碼清單12.2 配置類

package com.hashnode.proj0001firstspringsecurity.config;import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {//設(shè)置認(rèn)證方法http.oauth2Login();//指定一個用戶需要經(jīng)過認(rèn)證才能提出請求http.authorizeRequests().anyRequest().authenticated();}
}

在代碼清單12.2中,我們在HttpSecurity對象上調(diào)用一個新方法:oauth2Login()。和httpBasic()或formLogin()一樣,oauth2Login()只是在過濾器鏈中添加了一個新的認(rèn)證過濾器。 我們在第9章中討論了過濾器,在那里你了解到Spring Security有一些filter實現(xiàn),你也可以在過濾器鏈中添加自定義的。在這種情況下,當(dāng)你調(diào)用oauth2Login()方法時,框架添加到過濾器鏈的過濾器是OAuth2LoginAuthenticationFilter(圖12.13)。這個過濾器攔截請求,并為OAuth 2認(rèn)證應(yīng)用所需的邏輯。

image-20230129162128639

圖12.13 通過調(diào)用HttpSecurity對象的oauth2Login()方法,我們將OAuth2LoginAuthenticationFilter添加到過濾器鏈中。它攔截請求并應(yīng)用OAuth 2認(rèn)證邏輯。

12.5.3 實現(xiàn)客戶注冊

在本節(jié)中,我們將討論如何實現(xiàn)OAuth 2客戶端和授權(quán)服務(wù)器之間的鏈接。如果你想讓你的應(yīng)用程序真正有所作為,這一點至關(guān)重要。 如果你現(xiàn)在按原樣啟動它,你將無法訪問主頁面。不能訪問該頁面的原因是,你指定了對于任何請求,用戶都需要進行認(rèn)證,但你沒有提供任何認(rèn)證的方式。我們需要確定 GitHub 是我們的授權(quán)服務(wù)器。為此,Spring Security定義了ClientRegistration接口。

ClientRegistration接口代表OAuth 2架構(gòu)中的客戶端。對于客戶端,你需要定義其所有需要的細節(jié),其中我們有:

  • 客戶端ID和密碼
  • 用于認(rèn)證的授予類型
  • 重定向URI
  • 范圍

你可能還記得第12.3節(jié),應(yīng)用程序需要所有這些細節(jié)來進行認(rèn)證過程。Spring Security還提供了一種簡單的方法來創(chuàng)建一個構(gòu)建器的實例,類似于你從第2章開始用來構(gòu)建UserDetails實例的方法。代碼清單12.3顯示了如何用Spring Security提供的構(gòu)建器來構(gòu)建這樣一個實例,來代表我們的客戶端實現(xiàn)。

代碼清單12.3 創(chuàng)建一個ClientRegistration實例

private ClientRegistration clientRegistration() {ClientRegistration cr = ClientRegistration.withRegistrationId("github").clientId("a7553955a0c534ec5e6b").clientSecret("1795b30b425ebb79e424afa51913f1c724da0dbb").scope(new String[]{"read:user"}).authorizationUri("https://github.com/login/oauth/authorize").tokenUri("https://github.com/login/oauth/access_token").userInfoUri("https://api.github.com/user").userNameAttributeName("id").clientName("GitHub").authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).redirectUriTemplate("{baseUrl}/{action}/oauth2/code/{registrationId}").build();return cr;
}

所有這些細節(jié)是怎么來的?我知道清單12.3第一眼看上去很嚇人,但它只不過是設(shè)置了客戶的ID和密碼。另外,在清單12.3中,我定義了作用域(授予的權(quán)限)、一個客戶名稱和一個我選擇的注冊ID。除了這些細節(jié),我還必須提供授權(quán)服務(wù)器的URL:

  • Authorization URI 客戶端重定向用戶進行認(rèn)證的URI。
  • Token URI 客戶端為獲得訪問token和刷新token而調(diào)用的URI,如12.3節(jié)所述
  • User info URI 客戶端在獲得訪問token后可以調(diào)用的URI,以獲得關(guān)于用戶的更多細節(jié)。

我是從哪里得到這些URI的?好吧,如果授權(quán)服務(wù)器不是你開發(fā)的,就像我們的情況一樣,你需要從文檔中獲取它們。以GitHub為例,你可以在這里找到它們:

https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/

Spring Security甚至比這更聰明。該框架定義了一個名為CommonOAuth2Provider的類。這個類部分地定義了你可以用于認(rèn)證的最常見的提供者的ClientRegistration實例,其中包括:

  • Google
  • GitHub
  • Facebook
  • Okta

清單12.4 使用CommonOAuth2Provider類

private ClientRegistration clientRegistration() {return CommonOAuth2Provider.GITHUB.getBuilder("github").clientId("a7553955a0c534ec5e6b").clientSecret("1795b30b425ebb79e424afa51913f1c724da0dbb").build();
}

正如你所看到的,這要干凈得多,你不必手動尋找和設(shè)置授權(quán)服務(wù)器的URL。當(dāng)然,這只適用于普通提供商。如果你的授權(quán)服務(wù)器不在常見的提供者之列,那么你沒有其他選擇,只能完全按照清單12.3中的定義ClientRegistration。

注意 使用CommonOAuth2Provider類的值也意味著你依賴于你使用的提供者不會改變URL和其他相關(guān)值。雖然這不太可能,但如果你想避免這種情況,可以選擇實現(xiàn)代碼清單12.3中的ClientRegistration。這使得你可以在配置文件中配置URL和相關(guān)的提供者的值。

在本節(jié)的最后,我們?yōu)榕渲妙愄砑恿艘粋€私有方法,該方法將返回ClientRegistration對象,如下表所示。在第12.5.4節(jié)中,你將學(xué)習(xí)如何為Spring Security注冊這個客戶端注冊對象,以便將其用于驗證。

清單12.5 在配置類中建立ClientRegistration對象

package com.laurentiuspilca.ssia.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {private ClientRegistration clientRegistration() {return CommonOAuth2Provider.GITHUB.getBuilder("github").clientId("a7553955a0c534ec5e6b").clientSecret("1795b30b425ebb79e424afa51913f1c724da0dbb").build();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.oauth2Login();http.authorizeRequests().anyRequest().authenticated();}
}

12.5.4 實現(xiàn)ClientRegistrationRepository

在這一節(jié)中,你將學(xué)習(xí)如何為Spring Security注冊ClientRegistration實例,以用于認(rèn)證。。為此,Spring Security使用一個ClientRegistrationRepository類型的對象(圖12.14)。

image-20230129164239675

圖12.14 ClientRegistrationRepository 檢索ClientRegistration細節(jié)(客戶ID,客戶密碼,URL,作用域,等等)。認(rèn)證過濾器需要這些細節(jié)用于認(rèn)證流程。

ClientRegistrationRepository接口類似于UserDetailsService接口,你在第二章已經(jīng)了解到。就像UserDetailsService對象通過用戶名找到UserDetails一樣,Client-RegistrationRepository對象通過注冊ID找到ClientRegistration。

你可以實現(xiàn)ClientRegistrationRepository接口來告訴框架在哪里可以找到ClientRegistration實例。Spring Security為我們提供了一個ClientRegistrationRepository的實現(xiàn),它將ClientRegistration的實例存儲在內(nèi)存中。正如你所猜測的,這與InMemoryUserDetailsManager對UserDetails實例的工作原理類似。我們在第三章討論了InMemoryUserDetailsManager。

為了結(jié)束我們的應(yīng)用實現(xiàn),我使用InMemoryClientRegistrationRepository實現(xiàn)定義了一個ClientRegistrationRepository,并將其注冊為Spring上下文中的一個bean。

我把我們在12.5.3節(jié)中建立的ClientRegistration實例添加到InMemoryClientRegistrationRepository中,把它作為參數(shù)提供給InMemoryClientRegistrationRepository構(gòu)造函數(shù)。你可以在下一個代碼清單中找到這段代碼。

代碼清單12.6 注冊ClientRegistration對象

  • 方式1
package com.hashnode.proj0001firstspringsecurity.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {private ClientRegistration clientRegistration() {return CommonOAuth2Provider.GITHUB.getBuilder("github").clientId("a7553955a0c534ec5e6b").clientSecret("1795b30b425ebb79e424afa51913f1c724da0dbb").build();}public ClientRegistrationRepository clientRepository() {ClientRegistration c = clientRegistration();return new InMemoryClientRegistrationRepository(c);}@Overrideprotected void configure(HttpSecurity http) throws Exception {//設(shè)置認(rèn)證方法http.oauth2Login(c -> {c.clientRegistrationRepository(clientRepository());});//指定一個用戶需要經(jīng)過認(rèn)證才能提出請求http.authorizeRequests().anyRequest().authenticated();}
}
  • 方式2
package com.laurentiuspilca.ssia.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.oauth2.client.CommonOAuth2Provider;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;@Configuration
public class ProjectConfig extends WebSecurityConfigurerAdapter {private ClientRegistration clientRegistration() {return CommonOAuth2Provider.GITHUB.getBuilder("github").clientId("a7553955a0c534ec5e6b").clientSecret("1795b30b425ebb79e424afa51913f1c724da0dbb").build();}public ClientRegistrationRepository clientRepository() {var c = clientRegistration();return new InMemoryClientRegistrationRepository(c);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.oauth2Login();http.authorizeRequests().anyRequest().authenticated();}
}

注意 一個配置選項和另一個一樣好,但請記住我們在第二章中討論的內(nèi)容。為了使你的代碼易于理解,避免混合配置方法。要么使用在上下文中用bean設(shè)置每一個東西的方法,要么使用代碼內(nèi)聯(lián)配置風(fēng)格。

12.5.5 Spring Boot配置的魅力

在這一節(jié)中,我將向你展示第三種方法,直接從屬性文件中構(gòu)建ClientRegistration和ClientRegistrationRepository對象。這種方法在Spring Boot項目中并不罕見。我們也可以看到這種情況發(fā)生在其他對象上。

例如,我們經(jīng)??吹礁鶕?jù)屬性文件配置的數(shù)據(jù)源。下面的代碼片斷顯示了如何在application.properties文件中為我們的例子設(shè)置client registration。

spring.security.oauth2.client.registration.github.client-id=a7553955a0c534ec5e6b
spring.security.oauth2.client.registration.github.client-secret=1795b30b425ebb79e424afa51913f1c724da0dbb

在這個片段中,我只需要指定客戶端ID和客戶端密碼。因為提供者的名字是github,Spring Boot知道從CommonOAuth2Provider類中獲取有關(guān)URI的所有細節(jié)?,F(xiàn)在,我的配置類看起來就像下面代碼清單。

@Configuration
public class ProjectConfigextends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.oauth2Login();http.authorizeRequests().anyRequest().authenticated();}
}

我們不需要指定關(guān)于ClientRegistration和ClientRegistrationRepository的任何細節(jié),因為它們是由Spring Boot根據(jù)屬性文件自動創(chuàng)建的。如果我們使用Spring Security已知的常見提供商以外的提供商,我們還需要使用以spring.security.oauth2.client.provider開頭的屬性組來指定授權(quán)服務(wù)器的細節(jié)。下面的代碼片段為你提供了一個例子。

spring.security.oauth2.client.provider.myprovider.authorization-uri=<some uri>
spring.security.oauth2.client.provider.myprovider.token-uri=<some uri>

在我需要在內(nèi)存中擁有一個或多個authentication providers的情況下,就像我們在當(dāng)前的例子中所做的那樣,我更喜歡按照我在本節(jié)中介紹的方式進行配置。它更干凈,更容易管理。

但是如果我們需要一些不同的東西,比如將客戶的注冊信息存儲在數(shù)據(jù)庫中或者從網(wǎng)絡(luò)服務(wù)中獲取,那么我們就需要創(chuàng)建一個自定義的ClientRegistration-
Repository實現(xiàn)。在這種情況下,我們需要按照你在12.5.5節(jié)中學(xué)到的方法來設(shè)置它。

12.5.6 獲取已驗證用戶的詳細信息

在本節(jié)中,我們將討論獲取和使用認(rèn)證用戶的詳細信息。你已經(jīng)知道,在Spring Security架構(gòu)中,是由SecurityContext來存儲認(rèn)證用戶的詳細信息。一旦認(rèn)證過程結(jié)束,負責(zé)的過濾器會將認(rèn)證對象存儲在SecurityContext中。應(yīng)用程序可以從那里獲取用戶的詳細信息,并在需要時使用它們。同樣的情況也發(fā)生在OAuth 2認(rèn)證中。

在這種情況下,框架所使用的認(rèn)證對象的實現(xiàn)被命名為OAuth2AuthenticationToken。你可以直接從SecurityContext中獲取它,或者讓Spring Boot在api的一個參數(shù)中為你注入它,正如你在第6章中學(xué)到的那樣。下面的列表顯示了我如何改變控制器來接收并在控制臺中打印用戶的詳細信息。

代碼清單12.9 使用已登錄用戶的詳細信息

package com.hashnode.proj0001firstspringsecurity.controller;import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;import java.util.logging.Logger;@Controller
public class MainController {private Logger logger =Logger.getLogger(MainController.class.getName());@GetMapping("/")public String main(OAuth2AuthenticationToken token) {//Spring Boot自動在方法的參數(shù)中注入代表用戶的Authentication對象。logger.info(String.valueOf(token));return "main.html";}
}

12.5.7 測試應(yīng)用程序

在本節(jié)中,我們將測試本章中的應(yīng)用程序。在檢查功能的同時,我們遵循OAuth 2授權(quán)代碼授予類型的步驟(圖12.15),以確保你正確理解它,并觀察Spring Security是如何通過我們的配置來應(yīng)用它的。

image-20230129174233986

圖12.15 該應(yīng)用將GitHub作為授權(quán)服務(wù)器,同時也作為資源服務(wù)器。 當(dāng)用戶想要登錄時,客戶端會將用戶重定向到GitHub的登錄頁面。當(dāng)用戶成功登錄后,GitHub 會向我們的應(yīng)用程序回撥一個授權(quán)碼。我們的應(yīng)用程序使用該授權(quán)碼來請求一個訪問token。然后,應(yīng)用程序可以通過提供訪問token從資源服務(wù)器(GitHub)訪問用戶詳情。資源服務(wù)器的響應(yīng)提供了用戶的詳細信息和主頁面的URL。

我首先確定我沒有登錄到GitHub。我還確保我打開了一個瀏覽器來檢查請求導(dǎo)航的歷史。這個歷史記錄可以讓我了解OAuth 2流程中發(fā)生的步驟,也就是我們在12.3.1節(jié)中討論的步驟。如果我通過了認(rèn)證,那么應(yīng)用程序就會直接記錄我。然后我啟動應(yīng)用程序,在瀏覽器中訪問我們應(yīng)用程序的主頁面:

image-20230129174435444

應(yīng)用程序?qū)⑽抑囟ㄏ虻揭韵麓a片段中的URL(并在圖12.16中預(yù)發(fā))。這個URL被配置在GitHub的CommonOauth2Provider類中作為授權(quán)URL。

https://github.com/login?client_id=15a2c5a0e3fe921a223d&return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3D15a2c5a0e3fe921a223d%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A9090%252Flogin%252Foauth2%252Fcode%252Fgithub%26response_type%3Dcode%26scope%3Dread%253Auser%26state%3DSS5dh9rn0evuxXqBc_-wvgdlecYB8VpcTB-EgcGgtqg%253D

image-20230129175309685

圖 12.16 進入主頁面后,瀏覽器將我們重定向到 GitHub 登錄。在 Chrome 的控制臺工具中,我們可以看到對 localhost 的調(diào)用,然后是對 GitHub 授權(quán)api的調(diào)用。

我們的應(yīng)用程序?qū)⑺璧牟樵儏?shù)附加到URL上,正如我們在第12.3.1節(jié)所討論的那樣。這些參數(shù)是

  • response_type,其值為code
  • client_id
  • scope(值read:user也定義在CommonOauth2Provider類中)。
  • state值為CSRF令牌

image-20230129175825394

我們使用我們的GitHub憑證,用GitHub登錄我們的應(yīng)用程序。正如你在圖12.17中看到的那樣,我們通過了認(rèn)證并被重定向回來。

image-20230129180759295

圖 12.17 填寫完憑證后,GitHub 將我們重定向到我們的應(yīng)用程序。現(xiàn)在我們可以看到主頁面,應(yīng)用程序可以利用訪問令牌從 GitHub 訪問用戶的詳細信息。

下面的代碼片斷顯示了GitHub給我們響應(yīng)的URL。你可以看到,GitHub提供了授權(quán)碼,我們的應(yīng)用程序使用該授權(quán)碼來請求獲取token。

http://localhost:9090/login/oauth2/code/github?code=4ad786953479921c594d&state=yH8bDv81m9QsIRCT3urcU67forv-GSGuR3QulqAKH7Y=

可以看到返回的token如下:

image-20230129182005307

我們不會從瀏覽器中看到對token對象獲取 api的調(diào)用,因為這直接發(fā)生在我們的應(yīng)用程序中。但我們可以相信,應(yīng)用程序設(shè)法獲得了一個token對象,因為我們可以看到控制臺中打印的用戶詳細信息。這意味著應(yīng)用程序獲取了token對象。接下來的代碼片段向你展示了這個輸出的一部分。

Name: [43921235],
Granted Authorities: [[ROLE_USER, SCOPE_read:user]], User Attributes:
[{login=lspil, id=43921235, node_id=MDQ6VXNlcjQzOTIxMjM1,
avatar_url=https://avatars3.githubusercontent.com/u/43921235?v=4,
gravatar_id=, url=https://api.github.com/users/lspil, html_url=https://
github.com/lspil, followers_url=https://api.github.com/users/lspil/
followers, following_url=https://api.github.com/users/lspil/following{/
other_user}, …

總結(jié)

  • OAuth 2框架描述了允許一個實體代表其他人訪問資源的方法。我們在應(yīng)用程序中使用它來實現(xiàn)認(rèn)證和授權(quán)邏輯。
  • 一個應(yīng)用程序可以用來獲取訪問令牌的不同流程被稱為授予。根據(jù)系統(tǒng)結(jié)構(gòu)的不同,你需要選擇一個合適的授予類型。
    • 認(rèn)證碼授予類型的工作方式是允許用戶直接在授權(quán)服務(wù)器上進行認(rèn)證,這使得客戶端可以獲得一個訪問令牌。當(dāng)用戶不信任客戶端并且不想與之分享他們的憑證時,我們選擇這種授予類型。
    • 密碼授予類型意味著用戶與客戶端共享其憑證。只有在你能信任客戶端的情況下,你才應(yīng)該應(yīng)用這個。
    • 客戶端憑證授予類型意味著客戶端只通過驗證其憑證來獲得令牌。當(dāng)客戶端需要調(diào)用資源服務(wù)器的一個不是用戶資源的api時,我們選擇這種授予類型。
  • Spring Security實現(xiàn)了OAuth 2框架,允許你用幾行代碼在你的應(yīng)用程序中實現(xiàn)它。
  • 在Spring Security中,你可以使用ClientRegistration的一個實例來表示客戶在授權(quán)服務(wù)器上的注冊。
  • Spring Security OAuth 2實現(xiàn)中負責(zé)尋找特定客戶端注冊的組件被稱為ClientRegistrationRepository。在用Spring Security實現(xiàn)OAuth 2客戶端時,你需要定義一個至少有一個客戶端注冊的ClientRegistrationRepository對象。
http://m.risenshineclean.com/news/61282.html

相關(guān)文章:

  • 湖北網(wǎng)站開發(fā)網(wǎng)站多少錢
  • 門戶網(wǎng)站html模板參考網(wǎng)是合法網(wǎng)站嗎?
  • wordpress批量修改圖片標(biāo)題seo中文意思是
  • 網(wǎng)站都有什么費用千鋒教育培訓(xùn)怎么樣
  • wordpress的文章分類班級優(yōu)化大師下載
  • 網(wǎng)站域名包括菏澤資深seo報價
  • 軟件界面設(shè)計工具下載刷seo快速排名
  • wordpress 插件太多seo長尾快速排名
  • 做畫冊好的國外網(wǎng)站推薦如何關(guān)閉2345網(wǎng)址導(dǎo)航
  • 現(xiàn)在的網(wǎng)站設(shè)計前端seo主要優(yōu)化哪些
  • 圖書館網(wǎng)站建設(shè)優(yōu)化合作平臺
  • 工業(yè)皮帶怎么做免費的網(wǎng)站情感式軟文廣告
  • 天津房地產(chǎn)集團網(wǎng)站建設(shè)地推接單正規(guī)平臺
  • 品牌網(wǎng)站建站公司如何推廣我的網(wǎng)站
  • 做poster的網(wǎng)站提升seo排名的方法
  • 做網(wǎng)站流量錢誰給深圳網(wǎng)絡(luò)優(yōu)化公司
  • 網(wǎng)站seo博客西安seo霸屏
  • wordpress如何設(shè)置網(wǎng)站描述小程序免費制作平臺
  • 網(wǎng)站制作網(wǎng)站建設(shè)競價開戶
  • 手機做推廣比較好的網(wǎng)站關(guān)鍵詞排名怎么做上首頁
  • 找工作網(wǎng)站谷歌在線瀏覽入口
  • 自己做網(wǎng)站的過程搜索引擎seo是什么意思
  • 做商城網(wǎng)站需要備案嗎鄒平縣seo網(wǎng)頁優(yōu)化外包
  • 中山網(wǎng)站建設(shè)找丁生商城推廣軟文范文
  • 有效的網(wǎng)站建設(shè)百度怎么發(fā)布短視頻
  • 東營建筑信息網(wǎng)北京網(wǎng)絡(luò)seo經(jīng)理
  • wordpress 強制換行網(wǎng)站seo軟件
  • 學(xué)做課件的網(wǎng)站新媒體營銷推廣公司
  • 給我一個可以看片的免費seo排名官網(wǎng)
  • 網(wǎng)站建設(shè)的意義線上直播營銷策劃方案