前言
接着授權模式聊,這次說說Authorization Code(授權碼)模式,熟悉的微博接入、微信接入、QQ接入都是這種方式(這里說的是oauth2.0的授權碼模式),從用戶體驗上來看,交互方式和Implicit沒啥改變,隨便找個網站瞅瞅,如慕課網(很不錯的學習網站)的登錄流程,見下圖:
但其實在代碼流程上是不太一樣的,接下來邊擼(我說的是敲代碼)邊聊。
正文
Authorization Code(授權碼)模式比Implicit多了一個授權碼的流程,即用戶認證成功之后,授權服務器不會馬上返回AccessToken,而是先返回一個code(這里稱為授權碼),然后客戶端通過code再去獲取Token,主要流程大概如下圖:
流程說明:
- 用戶通過瀏覽器(User-Agent)訪問第三方客戶端(Client);
- 如果客戶端需要進行認證授權,則將其重定向到認證服務器(Authorization server);
- 用戶(ResorceOwner)在認證服務器上進行認證;
- 認證服務器(Authorization server)驗證成功之后,返回code(授權碼);
- 客戶端帶上code(授權碼)再去授權服務器請求獲取AccessToken/IdToken;
- 授權服務器驗證code(授權碼)的有效性,驗證成功后返回Token;
- 后續用戶再操作客戶端的時候,若需訪問保護資源,直接在請求中帶上AccessToken即可;
- 最終資源服務器(Resource server)返回對應信息;
術語解釋:
- code(授權碼):授權服務器認證成功之后返回的code,這個code有時效性,而且只能使用一次。
通過上面的流程,Authorization Code(授權碼)模式其實更適合有后台的客戶端,比如MVC程序,接收code和通過code獲取Token的過程都在客戶端后台進行,用戶無感知;再加上code(授權碼)的時效和次數限制,相對來說,這種模式是比較安全的。IdentityServer4已經封裝好,所以擼碼很簡單,繼續搞起來↓↓↓
1. 授權服務器和資源服務器代碼先從上一節中拷貝過來;
-
對於資源服務器,還是不需要改動;
-
對於授權服務器,加個客戶端完事;
2. 創建一個MVC客戶端,引入相關包並配置OpenID Connect;
2.1 創建一個MVC項目,並引入對應的包,項目結構如下:
2.2 在Startup.cs文件中配置增加認證授權相關配置:
ConfigureServices方法中添加如下代碼:
注,在訪問API的時候,還需要加入:options.Scope.Add("orderApi"); 這個scope在授權服務器已經定義過的,之前的案例也有說到。
Configure方法中添加如下代碼:
2.3 將客戶端中Controller都增加[Authorize],表示將其保護起來,如果沒有通過認證授權,就不能訪問;
這樣HomeController中的所有Action都保護起來了,如果需要訪問,就需要先到授權服務器上進行認證授權。
3. 先跑起來看看效果,如果不出意外,應該沒問題;
哦豁!翻車了
當在授權服務器認證授權完成之后,理當正常跳轉到客戶端(這里用到的是谷歌瀏覽器,版本為8x),但是偏偏某有,報了一個很莫名其妙的錯,如下:
但通過吸取上一節Implicit的經驗,初步認為是Cookies沒在谷歌瀏覽器中寫入成功,於是就換了360瀏覽器試了試,沒毛病,一切如行雲流水一般,正常跳轉,原來是如下Cookie沒有成功寫入,所以找不到,在控制台的時候也有警告提示,沒有找到Cookies;
MVC客戶端控制台的提示:
解決措施
這是由於新版瀏覽器對Cookie策略的整改,而谷歌優先進行推廣,所以測試總是在谷歌瀏覽器出問題;和上一節授權處理器的方式一樣,如下:
在客戶端中新增一個處理類:SameSiteCookiesServiceCollectionExtensions.cs,代碼內容就不貼啦(git倉庫里有),這是公開代碼,大佬寫好的解決方案;
寫好處理類之后,直接使用即可,如下:
完成以上步驟,問題就解決啦;再去測試一把,果然沒有問題;
注: 如果MVC客戶端為Https的話就不會出現以上問題;這和SameSite
的三種模式有關:Strict
,Lax
,None
.這里留個小伙伴自己去擴充吧。
4. 在客戶端中獲取Claims信息及調用受保護的API資源;
先在導航菜單中增加獲取Claims和調用API的按鈕,因為用到的是MVC布局頁,直接在_Layout.cshtml中復制粘貼就完事,如下:
4.1 獲取Claims信息,代碼如下:
根據導航菜單的配置,在HomeController中增加一個UserInfo的Action,並根據Action新增對應的視圖文件UserInfo.csthml:
運行(啟動授權服務->啟動客戶端),點擊導航菜單UserInfo,如下:
4.2調用API(受保護資源)
在HomeController中增加一個CallAPI的Action,並根據Action新增對應的視圖文件CallAPI.csthml,代碼如下:
運行(啟動授權服務->啟動API資源服務->啟動客戶端),點擊CallAPI菜單,如下:
到這Authorization Code(授權碼)模式的簡單使用就差不多啦,后續的內部業務鑒權在后續的實戰項目中會說到; 細節流程留給小伙伴一步一步調試吧。
源碼地址:https://github.com/zyq025/IDS4Demo/tree/main/AuthorizationCode。
總結
在編寫測試Demo的時候,會出現很多細節的問題,所以建議小伙伴多敲敲代碼,不要復制的那種;另外還需要注意新版本瀏覽器對Cookies的限制,可能導致一些莫名其妙的錯誤,上文中有已經處理;關於Cookies的規則,大家可以找找資料瞅瞅。目前所有的案例都是基於內存存儲數據,在實際項目中肯定是需要將信息持久化的,所以下一篇說說IdentityServer4的持久化。
一個被程序搞丑的帥小伙,關注"Code綜藝圈",跟我一起學~