IdentityServer4之Authorization Code(授權碼)相對更安全


前言

接着授權模式聊,這次說說Authorization Code(授權碼)模式,熟悉的微博接入、微信接入、QQ接入都是這種方式(這里說的是oauth2.0的授權碼模式),從用戶體驗上來看,交互方式和Implicit沒啥改變,隨便找個網站瞅瞅,如慕課網(很不錯的學習網站)的登錄流程,見下圖:

image-20210207184102915

但其實在代碼流程上是不太一樣的,接下來邊擼(我說的是敲代碼)邊聊。

正文

Authorization Code(授權碼)模式比Implicit多了一個授權碼的流程,即用戶認證成功之后,授權服務器不會馬上返回AccessToken,而是先返回一個code(這里稱為授權碼),然后客戶端通過code再去獲取Token,主要流程大概如下圖:

image-20210207212131876

流程說明:

  1. 用戶通過瀏覽器(User-Agent)訪問第三方客戶端(Client);
  2. 如果客戶端需要進行認證授權,則將其重定向到認證服務器(Authorization server);
  3. 用戶(ResorceOwner)在認證服務器上進行認證;
  4. 認證服務器(Authorization server)驗證成功之后,返回code(授權碼)
  5. 客戶端帶上code(授權碼)再去授權服務器請求獲取AccessToken/IdToken;
  6. 授權服務器驗證code(授權碼)的有效性,驗證成功后返回Token;
  7. 后續用戶再操作客戶端的時候,若需訪問保護資源,直接在請求中帶上AccessToken即可;
  8. 最終資源服務器(Resource server)返回對應信息;

術語解釋:

  • code(授權碼):授權服務器認證成功之后返回的code,這個code有時效性,而且只能使用一次

通過上面的流程,Authorization Code(授權碼)模式其實更適合有后台的客戶端,比如MVC程序,接收code和通過code獲取Token的過程都在客戶端后台進行,用戶無感知;再加上code(授權碼)的時效和次數限制,相對來說,這種模式是比較安全的。IdentityServer4已經封裝好,所以擼碼很簡單,繼續搞起來↓↓↓

1. 授權服務器和資源服務器代碼先從上一節中拷貝過來;

  • 對於資源服務器,還是不需要改動;

  • 對於授權服務器,加個客戶端完事;

    image-20210208234514235

2. 創建一個MVC客戶端,引入相關包並配置OpenID Connect;

2.1 創建一個MVC項目,並引入對應的包,項目結構如下:

image-20210208234845093

2.2 在Startup.cs文件中配置增加認證授權相關配置:

ConfigureServices方法中添加如下代碼:

image-20210208235531680

注,在訪問API的時候,還需要加入:options.Scope.Add("orderApi"); 這個scope在授權服務器已經定義過的,之前的案例也有說到。

Configure方法中添加如下代碼:

image-20210208235935257

2.3 將客戶端中Controller都增加[Authorize],表示將其保護起來,如果沒有通過認證授權,就不能訪問;

image-20210209000133987

這樣HomeController中的所有Action都保護起來了,如果需要訪問,就需要先到授權服務器上進行認證授權。

3. 先跑起來看看效果,如果不出意外,應該沒問題;

哦豁!翻車了

image-20210209001620304

當在授權服務器認證授權完成之后,理當正常跳轉到客戶端(這里用到的是谷歌瀏覽器,版本為8x),但是偏偏某有,報了一個很莫名其妙的錯,如下:

image-20210208172332573

但通過吸取上一節Implicit的經驗,初步認為是Cookies沒在谷歌瀏覽器中寫入成功,於是就換了360瀏覽器試了試,沒毛病,一切如行雲流水一般,正常跳轉,原來是如下Cookie沒有成功寫入,所以找不到,在控制台的時候也有警告提示,沒有找到Cookies;

image-20210208234250298

MVC客戶端控制台的提示:

image-20210209001800305

解決措施

這是由於新版瀏覽器對Cookie策略的整改,而谷歌優先進行推廣,所以測試總是在谷歌瀏覽器出問題;和上一節授權處理器的方式一樣,如下:

客戶端中新增一個處理類:SameSiteCookiesServiceCollectionExtensions.cs,代碼內容就不貼啦(git倉庫里有),這是公開代碼,大佬寫好的解決方案;

寫好處理類之后,直接使用即可,如下:

image-20210128164529597

完成以上步驟,問題就解決啦;再去測試一把,果然沒有問題;

注: 如果MVC客戶端為Https的話就不會出現以上問題;這和SameSite的三種模式有關:Strict,Lax,None.這里留個小伙伴自己去擴充吧。

4. 在客戶端中獲取Claims信息及調用受保護的API資源;

先在導航菜單中增加獲取Claims和調用API的按鈕,因為用到的是MVC布局頁,直接在_Layout.cshtml中復制粘貼就完事,如下:

image-20210209105104097

4.1 獲取Claims信息,代碼如下:

根據導航菜單的配置,在HomeController中增加一個UserInfo的Action,並根據Action新增對應的視圖文件UserInfo.csthml:

image-20210209112334677

運行(啟動授權服務->啟動客戶端),點擊導航菜單UserInfo,如下:

image-20210209103558145

4.2調用API(受保護資源)

在HomeController中增加一個CallAPI的Action,並根據Action新增對應的視圖文件CallAPI.csthml,代碼如下:

image-20210209112804675

運行(啟動授權服務->啟動API資源服務->啟動客戶端),點擊CallAPI菜單,如下:

image-20210209113129414

到這Authorization Code(授權碼)模式的簡單使用就差不多啦,后續的內部業務鑒權在后續的實戰項目中會說到; 細節流程留給小伙伴一步一步調試吧。

源碼地址:https://github.com/zyq025/IDS4Demo/tree/main/AuthorizationCode。

總結

在編寫測試Demo的時候,會出現很多細節的問題,所以建議小伙伴多敲敲代碼,不要復制的那種;另外還需要注意新版本瀏覽器對Cookies的限制,可能導致一些莫名其妙的錯誤,上文中有已經處理;關於Cookies的規則,大家可以找找資料瞅瞅。目前所有的案例都是基於內存存儲數據,在實際項目中肯定是需要將信息持久化的,所以下一篇說說IdentityServer4的持久化。

一個被程序搞丑的帥小伙,關注"Code綜藝圈",跟我一起學~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM