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

Code綜藝圈發表於2021-02-22

前言

接著授權模式聊,這次說說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綜藝圈",跟我一起學~

相關文章