IdentityServer4 之Client Credentials走起来
前言
API裸奔是絕對不允許滴,之前專門針對這塊分享了jwt的解決方案(WebApi接口裸奔有風(fēng)險);那如果是微服務(wù),又怎么解決呢?每一個服務(wù)都加認(rèn)證授權(quán)也可以解決問題,只是顯得認(rèn)證授權(quán)這塊冗余,重復(fù)在搞事情;IT大佬肯定容忍不了,對于微服務(wù)架構(gòu),統(tǒng)一的認(rèn)證授權(quán)中心那是必須的。
隨著.NetCore的發(fā)布,IdentityServer4隨之而出,是.Net Foundation的成員之一,專門針對.NetCore而出的認(rèn)證授權(quán)框架,當(dāng)前.Net圈是比較火的啦;再配上微服務(wù)認(rèn)證授權(quán)的必要性,我決定以此開始入手進(jìn)行微服務(wù)架構(gòu)學(xué)習(xí)分享;
主要的學(xué)習(xí)分享思路為敲代碼為向?qū)?#xff0c;如果遇到相關(guān)理論概念,結(jié)合代碼案例進(jìn)行解釋,不在單獨(dú)針對理論知識整理相關(guān)文章(主要是擔(dān)心歸納總結(jié)不好,讓小伙伴疑惑,所以就想著結(jié)合應(yīng)用案例解釋比較容易理解)。
正文
IdentityServer4 主要的功能就是認(rèn)證和授權(quán),其他功能這里先假裝不知道;主要目的就是想用其統(tǒng)一保護(hù)各個微服務(wù)的接口;先來理解一下認(rèn)證和授權(quán):
授權(quán)(Authorization):在用戶身份認(rèn)證通過之后,授予用戶訪問資源的過程或是用戶授予第三系統(tǒng)訪問自己資源的過程,資源可能是個人信息、文件、數(shù)據(jù)、接口等;OAuth2是現(xiàn)在比較火的授權(quán)標(biāo)準(zhǔn),對于授權(quán)流程,后續(xù)會舉例說明;
在公司,假如小伙伴是領(lǐng)導(dǎo),在出差或休假的時候,通常會通過口頭、郵件、信息等方式將一些工作臨時委托給某人處理,比如簽字、參會等,這個過程叫做授權(quán),如果沒有授權(quán),簽字無效,也不能隨意參會;
認(rèn)證(Authentication):用戶身份認(rèn)證,可以將其理解為登錄;系統(tǒng)驗(yàn)證身份憑據(jù)是否合法,比如用戶名/密碼、人臉識別等方式;OpenId Connect是目前比較流行的身份認(rèn)證標(biāo)準(zhǔn)協(xié)議,OpenID是一個去中心化的網(wǎng)上身份認(rèn)證系統(tǒng),OpenID Connect是在OAuth2基礎(chǔ)進(jìn)行擴(kuò)展,增加身份認(rèn)證和相關(guān)身份標(biāo)識信息;
稍微有點(diǎn)規(guī)模的公司,通常都有自己的辦公樓,有專門的保安人員,管控非公司人員的進(jìn)入, 如果是公司人員,刷卡識別即可進(jìn)入,如果是非公司人員需要登記個人信息確認(rèn)才能進(jìn)入,這個過程可以理解為身份認(rèn)證;只有驗(yàn)證信息之后才能進(jìn)入公司。
IdentityServer4 已經(jīng)將OpenID Connect和OAuth 2.0封裝實(shí)現(xiàn),開發(fā)者開箱即用,無需再重新自己實(shí)現(xiàn)細(xì)節(jié),但如果有需要,小伙伴可以在IdentitySever4基礎(chǔ)進(jìn)行擴(kuò)展個性化需求;
在授權(quán)過程中,根據(jù)應(yīng)用場景不同,有四種授權(quán)模式可以選擇,如下:
Authorization Code(授權(quán)碼):最完整的授權(quán)模式,也是相對比較安全的模式,適用于有后臺的應(yīng)用程序,如MVC項(xiàng)目;
Implicit(簡化模式):簡化授權(quán)碼模式,適用于無后臺的應(yīng)用程序,如前后端分離項(xiàng)目;
Resource Owner Password Credentials(資源所有者密碼):直接通過用戶名和密碼獲得授權(quán),這種適用于高度信任的應(yīng)用,因?yàn)樾枰斎胗脩裘兔艽a,安全泄露風(fēng)險高;
**Client Credentials(客戶端模式) **:這是無用戶操作模式,適用于機(jī)器對機(jī)器的對接,沒有用戶干預(yù)的應(yīng)用,如后臺任務(wù)調(diào)度應(yīng)用,采集數(shù)據(jù)應(yīng)用等;
混合模式:以上四種的組合。
其他理論先不說了,我們邊擼碼邊聊,這樣記憶深刻一點(diǎn),這里就從最簡單的Client Credentials開始:
Client Credentials 客戶端授權(quán)模式
客戶端模式?jīng)]有用戶,就只是單純的機(jī)器對機(jī)器的交互,大概的流程如下:
流程簡要說明:
首先客戶端帶上憑據(jù)向授權(quán)服務(wù)器獲取AccessToken,這里的客戶端憑據(jù)是提前在授權(quán)服務(wù)器上備案過的;
授權(quán)服務(wù)器驗(yàn)證客戶端憑據(jù),成功之后直接返回AccessToken;
客戶端在帶上AccessToken訪問資源服務(wù)器;
資源服務(wù)器正常返回結(jié)果,如果沒有AccessToken是不能訪問受保護(hù)資源的;
來,結(jié)合流程看看代碼怎么實(shí)現(xiàn),一步一步來:
>>>先創(chuàng)建API項(xiàng)目---資源服務(wù)器
創(chuàng)建一個OrderController,并在里面新增一個Orders 接口,接口沒有進(jìn)行保護(hù);
接口沒有進(jìn)行保護(hù),可以任意訪問,如下:
>>>再創(chuàng)建認(rèn)證授權(quán)中心項(xiàng)目---授權(quán)服務(wù)器,將資源服務(wù)保護(hù)起來
以上的API接口裸奔是有風(fēng)險的,現(xiàn)在需要統(tǒng)一的認(rèn)證授權(quán)中心進(jìn)行保護(hù),如下:
新創(chuàng)建一個API項(xiàng)目,并引入IdentityServer4包,并在內(nèi)存中模擬相關(guān)數(shù)據(jù),方便測試;
術(shù)語解釋:
ApiScope:就是一個作用域范圍,生成的Token只能訪問指定范圍的資源;
Client:這里的客戶端就是應(yīng)用,比如MVC項(xiàng)目、純前端項(xiàng)目、Winfrom/WPF、APP等,必須首先在授權(quán)服務(wù)器中進(jìn)行備案并獲得授權(quán)服務(wù)器分配的標(biāo)識和密碼,后續(xù)用于獲取AccessToken;
模擬數(shù)據(jù)準(zhǔn)備好了,就在Startup中進(jìn)行對應(yīng)的注入和配置,并開啟中間件,如下:
這樣就初步完成授權(quán)服務(wù)器的搭建,這里監(jiān)聽的端口改為6100了,用Postman先來測測是否能正常獲取Token,如下:
可能有新手小伙伴會問,咋知道是這個地址能獲取token的?小伙伴可以在瀏覽器中輸入以下鏈接,即可看見授權(quán)服務(wù)器的相關(guān)信息(授權(quán)服務(wù)器地址+/.well-known/openid-configuration):
授權(quán)服務(wù)器已經(jīng)好了,準(zhǔn)備將資源服務(wù)器接入到授權(quán)服務(wù)器,對API接口進(jìn)行保護(hù)(ApiDemo項(xiàng)目中),如下:
注:ApiDemo項(xiàng)目中需要Microsoft.AspNetCore.Authentication.JwtBearer包,因?yàn)轫?xiàng)目是基于.NetCore3.1的,所以這里引用的包版本為3.1.10。
然后在接口上面加上[Authorize]特性,將接口保護(hù)起來,看運(yùn)行效果如下:
在Postman中測試,先獲取AccessToken,然后將獲取的AccessToken加入到Header中請求資源服務(wù)器中受保護(hù)的API,如下:
>>>真實(shí)客戶端訪問受保護(hù)API---控制臺
建一個控制臺項(xiàng)目,具體步驟如圖:
這里就不用文字說明步驟,小伙伴一邊看代碼,一邊看注釋,這樣應(yīng)該比較清晰點(diǎn):
static?async?Task?Main(string[]?args) {//?1.?創(chuàng)建一個HttpClient用于請求var?client?=?new?HttpClient();//?2.?獲取授權(quán)服務(wù)器的相關(guān)信息,IdentityModel已經(jīng)將其封裝好了var?disco?=?await?client.GetDiscoveryDocumentAsync("http://localhost:6100");//?3.?檢查是否請求錯誤if?(disco.IsError){//?錯誤就打印錯誤信息,然后直接返回Console.WriteLine(disco.Error);return;}//?4.?通過授權(quán)服務(wù)分配的標(biāo)識,向授權(quán)服務(wù)器請求AccessTokenvar?tokenResp?=?await?client.RequestClientCredentialsTokenAsync(new?ClientCredentialsTokenRequest{//?指定獲取token的地址,IdentityModel進(jìn)行封裝,直接使用即可Address?=?disco.TokenEndpoint,//?指定授權(quán)服務(wù)器分配的客戶端標(biāo)識ClientId?=?"client",//?指定授權(quán)服務(wù)器分的客戶端密碼ClientSecret?=?"ordersecret"});//?5.?檢查獲取Token是否成功if?(tokenResp.IsError){//?如果失敗,打印錯誤消息并返回Console.WriteLine(tokenResp.Error);return;}//?6.?創(chuàng)建一個請求API資源的HttpClientvar?apiClient?=?new?HttpClient();//?7.?將獲取到的Token以Bearer的方案設(shè)置在請求頭中apiClient.SetBearerToken(tokenResp.AccessToken);//?8.?向資源服務(wù)器中請求受保護(hù)的APIvar?contentResp?=?await?apiClient.GetAsync("http://localhost:5000/api/Order");//?9.?打印對應(yīng)的消息if?(contentResp.IsSuccessStatusCode){var?content?=?await?contentResp.Content.ReadAsStringAsync();Console.WriteLine(JArray.Parse(content));}else{Console.WriteLine(contentResp.StatusCode);}Console.ReadLine(); }到這里離完成還差一步了,什么,資源不是保護(hù)了嗎,受保護(hù)資源也能正常訪問了,還差哪一步?
在授權(quán)服務(wù)器模擬備案客戶端的時候,是不是指定了訪問資源的作用域,也就是說,備案過的客戶端只能訪問被授權(quán)的API資源,而現(xiàn)在拿到的AccessToken都能訪問資源服務(wù)器中所有受保護(hù)的資源,那是因?yàn)橘Y源服務(wù)器中的API資源沒有限制作用域訪問,而在實(shí)際項(xiàng)目中,并不是拿到AccessToken就能隨便訪問,需要做限制,繼續(xù)往下看↓↓↓
假如指定的scope值和客戶端在授權(quán)服務(wù)器中備案時設(shè)置的不一樣,就算獲取到AccessToken也不能正常訪問資源,會報403錯誤,這里我不截圖,小伙伴下去試試。
可能小伙伴會比較急,這都是啥玩意,全是硬編碼,垃圾文;?別別別,說好的學(xué)習(xí)分享嘛,一步一個腳印來嘛,最終肯定是小伙伴想要的,也是我學(xué)習(xí)的目標(biāo);
關(guān)于客戶端憑據(jù)生成的Token,在jwt.io網(wǎng)站解析看看,記錄一下,看看后面有用戶參與的情況,生成的Token解析出來會有什么不同呢,先上個圖(圖中解析出來的屬性之前在WebApi接口裸奔有風(fēng)險有說過):
總結(jié)
從這篇開始,后續(xù)會盡快更新學(xué)習(xí)分享,小伙伴們加入一起學(xué)習(xí),一起討論。下一篇說說Resource Owner Password Credentials.
一個被程序搞丑的帥小伙,關(guān)注"Code綜藝圈",跟我一起學(xué)~
總結(jié)
以上是生活随笔為你收集整理的IdentityServer4 之Client Credentials走起来的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Dapr微服务应用开发系列3:服务调用构
- 下一篇: Windows Terminal 新手入