在微服務場景中,身份認證通常是集中處理,這也是有别于單體應用一把梭哈的模式,其中,在微軟微服務白皮書中,提供了兩種身份認證模式:
- 網關,沒錯,原話是If you're using an API Gateway, the gateway is a good place to authenticate

- STS(security token service)
如果使用網關進行集中身份認證,微服務如果沒有設定了額外的安全性來驗證消息,就必須確定微服務在沒有經過網關的時候,不能直接被通路。從圖中也可看到,使用者資訊是由網關進行轉發請求時增加的。
如果使用STS進行集中身份認證,是可以直接通路服務,需要使用安全令牌服務(STS)的專用身份驗證單獨的服務(微服務)對使用者進行身份驗證。由STS頒發token,然後在請求微服務時就需要在請求中攜帶token。
我們文章後續:主要就是圍繞着STS安全令牌服務中間件IdentityServer4來具體展開的。
1.引言
1.1 實際遇到的問題
在之前一個單體web系統中,采用的是前後端分離,前端是
Vue 2.0
,後端使用的
ASP.NET Web Api 2.0
提供背景服務,登入子產品采用了
JWT(JSON WEB TOKEN)
的身份認證方式,在使用者請求時背景自定義解析JWT,然後把解析的部分結果裝進
HttpContext.Principal
,供後續授權操作。那時會遇到一個問題,前端并沒有mock開發,而是連接配接後端測試環境開發,前端在開發調試時,後端同步釋出最新接口,再加上IIS老版本釋出web服務,會有一個初次通路非常慢的問題,這時前端就會炸鍋,“後端挂了?請求不到JWT”,這個過程其實挺影響開發效率的,那時就萌生了把身份認證和授權單獨作為一個項目部署,由于本身屬于項目基礎設施,改動的頻率幾乎為0,業務層面也可以按需拆分,這可能就是我最早微服務思路的萌芽吧!
1.2 其他問題
微信公衆号開發
做過微信公衆号開發,我們大多數應用都希望使用者通過微信進行操作,然後留存使用者資訊,我們需要經過如下步驟:
- 向微信官方申請AppId,Appsecret,還有單獨一個加密密鑰
- 然後請求
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx6953deeefe22a83b&redirect_uri=your_address&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
- 這裡使用者通路,需要使用者授權
- 然後微信浏覽器會重定向至上一步的
指定的網址,且還會在redirect_uri
加上codequerystring
- 這個code,記住
- 然後就可以通過code,
在背景擷取access_token,openidhttps://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code
- access_token是憑證
- openid是微信的使用者體系
- 最後就能通過
,就能通過上一步中擷取到的access_token,擷取微信使用者的資訊https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN
類似的還有華為開放平台鑒權
2.OAuth 2.0
無論是微信公衆号,還是華為開發平台,他們為了構造自己的生态,運用自己龐大的使用者基數,去為第三方提供服務(如果可以的話,順便收錢),但是他們面臨的問題:
- 不能直接把使用者的資訊直接暴露,不然就是侵權行為
- 更不可能把使用者的使用者名和密碼直接暴露
怎麼辦?第三方應用程式需要知道目前操作的使用者身份,就需要身份驗證,這時OAuth協定應運而生,OAuth2.0引入了一個授權層,分離兩種不同的角色:
- 用戶端
- 資源所有者(使用者)
隻有使用者同意以後,伺服器才能向用戶端頒發令牌,用戶端通過令牌Token去請求資料,從某種意義上說OAuth2.0是一種委托協定,把原本可能需要使用者名和密碼才能拿到的資料,通過授權(Authorization)産生的access-token,并以此來進行相關通路。
簡單說系統使用者允許某個應用代表他們通路使用者自己能夠控制的資源。
OAuth 2.0包含如下主要内容:
2.1 授權方式
實際上,OAuth2.0有4種授權方式
- 授權碼-authorization-code
- 隐藏式-implicit
- 密碼式-password
- 用戶端憑證-client credentials
不管哪一種授權方式,第三方應用申請令牌之前,都需要像微信公衆号開發那樣,必須先到系統備案,說明自己的身份,然後會拿到兩個身份識别碼:用戶端 ID(client ID)和用戶端密鑰(client secret)。這是為了防止令牌被濫用,沒有備案過的第三方應用,是不會也不可能拿到令牌的。
2.2 端點
- Authorization Endpoint ,授權端點
- Token Endpoint ,Token端點
2.3 Scope
代表資源所有者在被保護的資源那裡的一些權限,可以把被保護的資源分為不同的scope,這個粒度由開發者自定義,常見的有角色
2.4 Access Token
- 用來通路被保護資源的憑據
- 代表了給用戶端頒發的授權,也就是委托給用戶端的權限
- OAuth2.0沒有對Token的格式和内容定義,隻有有一個要求:Access-token要描述出資源所有者授予權限的範圍,也就是scope,以及Access-token的有效期
2.5 Refresh Token
- 擷取Access token的憑據
- 由授權伺服器頒發
- 它是一個可選項
- 具備讓用戶端應用逐漸降低通路權限的能力
- 可以在Refresh Token請求重新擷取Access Token時,做一個設計,根據實際需求,給一個權限越來越低的token
3.OpenId Connect 1.0
上一節說過,OAuth 2.0是一種授權機制,是一種委托協定,但是不是一個身份認證協定。OAuth2.0的Access Token不含有身份認證資訊,也不是為用戶端準備的,本身也不對用戶端透明,Access Token真正的閱聽人是被保護的資源。
當然我們不排除一些簡單的系統鑒權要求,它隻需限制對是否具有有效安全令牌的使用者的通路,并不需求身份認證。
OAuth2.0設計的Access Token不含有身份認證資訊,但是JWT具有自包含特點,其實我們是可以把Access-Token設計為即具有身份資訊,又包含授權資訊。在一些簡單的單體應用中,把身份認證和授權揉在一起,根據Access_Token解析身份資訊和然後再根據身份資訊,配合設計的權限規則(db存儲)過濾請求,的确可以這樣做,事實上有一些開源項目,包括我自己,都這樣幹過。
在一些實際場景下,這種使用access-token作為身份認證的憑據是成立的,因為token是經過身份認證後,剛被建立的,再加上後續驗證與資料存儲的互動,可以確定無虞。
但是如果是在OAuth2.0中,這并不是擷取access-token的唯一方法。Refresh Token和assertions可以在使用者不存在的情況下擷取access token。而在某些情況下,使用者無需身份驗證即可獲得access token。另外使用者不存在,access-token通常還會存在很長時間。記住重要的一點:OAuth是一個授權協定,保護的是資源,突出一個保護,那麼必須保證使用者是存在的;access-token閱聽人是受保護的資源,用戶端是授權的提出者,是以受保護的資源不能僅通過token的單獨存在來判斷使用者是否存在,因為 OAuth 協定的性質和設計,在用戶端和受保護資源之間的連接配接上,使用者是不可用的。
當應用程式需要知道目前使用者的身份時,就需要進行身份認證。通常,這些應用程式代表該使用者管理資料,并需要確定該使用者隻能通路允許他通路的資料。
目前最常見的身份驗證協定是SAML2p、WS-Federation和OpenID Connect——SAML2p是最流行和部署最廣泛的。
OpenID Connect是三者中最新的一個,但是卻被認為是未來的發展方向,因為它對現代應用程式具有最大的潛力。它從一開始就為移動應用場景而建構,并被設計為對API友好。
OpenID Connect
- 是基于OAuth 2.0協定之上的簡單身份層,是在OAuth2.0之上做的一個擴充,相容OAuth2.0,身份驗證和API通路這兩個基本的安全問題被組合成一個協定——通常隻有一次到安全令牌服務(STS)的往返,是以這裡沒有詳細介紹OAuth2.0的授權流程的原因,因為OpenId Connect幾乎包含了整個OAuth2.0
OAuth 2.0與OpenID Connect1.0 映射表
OAuth2.0 | OpenID Connect 1.0 |
---|---|
資源所有者 | 使用者 |
用戶端 | 依賴方 |
授權伺服器+被保護資源 | 身份提供商 |
OpenId Connect 1.0包含如下主要内容:
3.1 ID Token
包含了使用者的認證資訊
3.2 UserInfo端點
擷取使用者資訊
3.3 預設
一組辨別身份的scopes和claims
- profile
- address
- phone
3.4 OpenID Connect 流程
- 授權碼流程-Authorization Code Flow
- 隐式流程-Implicit Flow
- 混合流程-Hybrid Flow
4.OpenID Connect 與 OAuth 2.0
下一篇我們将正式開始介紹對OpenID Connect+OAuth2.0這兩種協定的實作中間件:IdentityServer4,其經過高度優化,可以解決當今移動、本機和web應用程式等典型的安全問題。
在不同的文獻對可能會同一角色使用不同的術語,是以IdentityServer又可稱為安全令牌服務(STS)、身份提供者(IDP)、授權伺服器(AuthServer)、IP-STS等等。它的主要職責也就是OAuth2.0與OpenID Connect職責的綜合,
也是IdentityServer4的職責:
- 保護資源
- 使用本地使用者存儲或通過外部身份提供程式對使用者進行身份認證
- 提供session管理和單點登入
- 管理和認證用戶端
- 向用戶端頒發身份辨別和通路令牌
- 驗證Token
我們來回顧一下兩個協定的要點,
也是IdentityServer4的要點:
- 必須先到系統備案
- 授權端點
- 擷取Toekn端點
- 擷取使用者資訊端點
- 重新整理Token端點
- ID token
- 不同的權限scope
我們将在後續文章中一一對應職責與要點
參考連結
http://www.ruanyifeng.com/blog/2019/04/oauth_design.html
http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
https://www.cnblogs.com/linianhui/p/authentication-based-on-oauth2.html#auto-id-3
https://www.cnblogs.com/linianhui/p/oauth2-extensions-protocol-and-json-web-token.html#auto_id_2
https://www.cnblogs.com/linianhui/p/oauth2-authorization.html#auto_id_17
https://www.cnblogs.com/linianhui/p/oauth2-extensions-protocol-and-json-web-token.html#auto_id_2
https://www.cnblogs.com/linianhui/p/oauth2-extensions-protocol-and-json-web-token.html#auto-id-2
https://www.scottbrady91.com/OpenID-Connect/OpenID-Connect-Flows
https://identityserver4.readthedocs.io/en/latest/intro/big_picture.html
作者:Garfield
同步更新至個人部落格:http://www.randyfield.cn/
本文版權歸作者所有,未經許可禁止轉載,否則保留追究法律責任的權利,若有需要請聯系[email protected]
微信公衆号
掃描下方二維碼關注個人微信公衆号,實時擷取更多幹貨
作者:Garfield
同步更新至:http://www.randyfield.cn/
出處:http://www.cnblogs.com/RandyField/
本文版權歸作者和部落格園共有,未經許可禁止轉載,否則保留追究法律責任的權利,若有需要請聯系[email protected].