Microsoft.Owin.Security.OAuth搭建OAuth2.0授權服務端
目錄
-
前言
-
OAuth2.0簡介
-
授權模式 (SimpleSSO示例)
-
使用Microsoft.Owin.Security.SimpleSSO模擬OpenID認證
-
通過authorization code授權模式申請令牌
-
通過implicit授權模式申請令牌
-
通過password模式申請令牌
-
通過client credentials模式申請令牌
-
后話
前言
之前有分享這個項目源碼及簡介,不過因為文字講解太少,被和諧了。我重新總結下:
源碼:https://github.com/zhoufeihong/SimpleSSO
OAuth 2.0協議:http://www.rfcreader.com/#rfc6749
-------------------------------------------分割線
記得那個酷熱的夏天,面試官翹着二郎腿問:“知道單點登錄不?”,我毫不遲疑答到:“不就是限制用戶只能在一個地方登錄嗎!”。面試完回家,查資料,也是似懂非懂,COOKIE、跨域、令牌、主站都是些啥玩意!其實我就是個VS都沒摸過幾次的畢業生,單點登錄這種玩意是不是太高級了。
這次就是寫個項目練練手(這兩年手生了太多),想到當初在網上找了半天,關於單點登錄、OAuth 2.0也沒找到個完整的實例(概念、理論倒是比較多),就寫了這個項目。分享出來,希望可以給那些對單點登錄、OAuth 2.0實現比較困惑的C#開發人員一些幫助。同時項目里面有對於Autofac、AutoMapper、EF等等技術實踐方式(當然復制了很多代碼,我會盡量把源項目的License放上),希望在這些技術上也可以給你一些參考,項目可以直接運行(用戶名:admin密碼:123)。
昨天的文章因為文字講解太少了,被和諧了。不得不佩服博客園管理人員的專業水平,是你們如此細致的工作造就了博客園這么多優秀的文章,也造就了博客園的今天(拍個馬屁)。其實我就想貼幾張圖,你們看到效果后,自己去看代碼、敲代碼,這樣子會比較好些(其實我就是表達能力不好,怕詞不達意)。
廢話不多說了,這篇文章我簡單介紹下:
SimpleSSO授權第三方應用系統獲取用戶信息(OpenID認證)(類似於我們在新浪上點擊QQ快捷登錄,采用的授權碼模式(authorization code))
SimpleSSO授權基於瀏覽器應用系統獲取用戶信息(類似於我們通過微信瀏覽器點開第三方應用,采用的簡化模式(implicit))
第三方系統使用用戶名密碼申請獲取用戶令牌,然后用令牌獲取用戶信息(采用的密碼模式(password))
第三方系統申請自己的訪問令牌(類似於微信公眾號用申請令牌訪問自己公眾號信息(采用的客戶端模式client credentials))
第三方系統刷新用戶(本身)令牌(refreshtoken)
OAuth2.0簡介
OAuth2.0(開放授權)是一個開放標准,允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源,而無需將用戶名和密碼提供給第三方應用。具體你可以去百度(oauth2.0 阮一峰),文章關於oauth2.0理論的講解非常到位,網上的理論也非常多,之前沒有基礎的可以先去腦補下。
具體場景:QQ用戶在XX網站分享文章到QQ空間
剖析:
授權模式 (SimpleSSO授權示例)
前言:
關於授權模式如果不太清楚的建議:去百度(oauth2.0 阮一峰),文章關於對於授權模式的講解非常到位。Owin.OAuth的基礎,可以看看dudu寫的在ASP.NET中基於Owin OAuth使用Client Credentials Grant授權發放Token,一篇一篇看下去。
本節主要演示SimpleSSOTest站點通過各種授權模式到SimpleSSO站點申請令牌。如圖:
其中SimpleSSO站點為:http://localhost:8550,SimpleTest站點為:http://localhost:6111,后續會用到。
SimpleSSO關於OAuthAuthorizationServerOptions的配置:

其中兩個關於OAuth授權的實現類:
令牌生成接收:SimpleAuthenticationTokenProvider
授權總線:SimpleSSOOAuthProvider
授權示例:
1、使用Microsoft.Owin.Security.SimpleSSO模擬OpenID認證(authorization code模式)
1.1、Demo展示:
今天新加了Microsoft.Owin.Security.SimpleSSO組件(感興趣的可以看下Katana項目),主要方便第三方集成SimpleSSO登錄。
SimpleTest集成登錄需要完成如下代碼配置:

1.2、Demo請求流程(流程圖工具過期了,只能用文字了,省略了很多細節):
1)用戶點擊“使用Microsoft.Owin.Security.SimpleSSO模擬OpenID認證”下進入按鈕,將跳轉到http://localhost:6111/login/authsimplesso
2)authsimplesso接收用戶請求
1>如果用戶已經使用ExternalCookie在登錄,注銷ExternalCookie信息,獲取返回用戶信息。
2>當用戶未登錄,則將http返回狀態改為401,並且創建authenticationType為SimpleSSOAuthentication身份驗證,SimpleSSOAccountAuthenticationHandler將用戶重定向到http://localhost:8550/GrantCode/Authorize?client_id={0}&scope={1}&response_type=code&redirect_uri={2}&state={3}。
SimpleSSOAccountAuthenticationHandler重定向代碼:

3)GrantCode/Authorize接收用戶請求
1>如果為可信應用則不需要用戶同意,直接生成code讓用戶跳轉到http://localhost:6111/login/signin-simplesso?code={0}&state={1}
2>如果不是可信應用則跳轉到http://localhost:8550/OAuth/Grant用戶授權頁面,用戶點擊授權時跳轉到
4)http://localhost:6111/login/signin-simplesso?code={0}&state={1}請求處理,由SimpleSSOAccountAuthenticationHandler類處理
SimpleSSOAccountAuthenticationHandler代碼:

1>使用code獲取令牌
2>獲取用戶信息
3>SignIn(ExternalCookie)
4>重新跳轉到http://localhost:6111/login/authsimplesso,回到1.2-2)
2、通過authorization code授權模式申請令牌
2.1、Demo展示(這個demo請求實際上是可以跨域的):
2.2、Demo請求流程
1)用戶點擊“通過authorization code授權模式申請令牌”下進入按鈕,使用div加載url地址http://localhost:8550/GrantCode/Authorize?client_id=1&scope=user-base&response_type=code&redirect_uri=http://localhost:6111/api/Code/App1&state={隨機}。如果用戶沒有登錄的情況下請求這個路徑,會跳轉到登錄界面。
2)因為client_id=1應用為可信應用,所以直接生成code,請求http://localhost:6111/api/Code/App1?code=?&state={請求過來的值}
由SimpleSSOOAuthProvider方法AuthorizeEndpoint完成可信應用驗證,用戶令牌信息注冊,SimpleAuthenticationTokenProvider完成code生成
3)/api/Code/App1接收code、state
1)使用code獲取Access_Token
2)使用Access_Token獲取用戶信息
3)使用Refresh_Token刷新Access_Token
4)使用刷新后的Access_Token獲取用戶信息
/api/Code/App1代碼:

3、通過implicit授權模式申請令牌
3.1、Demo展示:
implicit模式是比較特別一種模式,由基於瀏覽器應用訪問用戶信息,所以生成的令牌直接為Access_Token,且Url為http://localhost:6111/TokenClient/ShowUser#access_token={0}&token_type={1}&state={2},瀏覽器端需要通過window.location.hash訪問。
3.2、Demo請求流程
1)用戶點擊""下進入,http://localhost:8550/GrantCode/Authorize?client_id=2&redirect_uri=http://localhost:6111/TokenClient/ShowUser&response_type=token&scope=user_base&state={隨機}
2)跳轉到用戶授權頁面,用戶授權后,返回http://localhost:6111/TokenClient/ShowUser#access_token={0}&token_type=bearer&state={2}
3)點擊Try Get Data,js使用access_token請求獲取用戶信息。
其中JS代碼:

4、通過password模式申請令牌
實現代碼:

5、通過client credentials模式申請令牌
實現代碼:

后話
寫的不夠清晰,建議看看源碼。關於OAuth的實現集中在SimpleSSOOAuthProvider,SimpleAuthenticationTokenProvider類。系統有很多不足的地方,后續我會抽時間迭代出一個穩定版本,這次畢竟只花了幾天時間。當然如果您有什么寶貴建議也可以郵件聯系我。