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ū)坛恚绻龅较嚓P(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)模式可以選擇,如下:

  1. Authorization Code(授權(quán)碼):最完整的授權(quán)模式犬辰,也是相對比較安全的模式嗦篱,適用于有后臺的應(yīng)用程序,如MVC項(xiàng)目幌缝;
  2. Implicit(簡化模式):簡化授權(quán)碼模式默色,適用于無后臺的應(yīng)用程序,如前后端分離項(xiàng)目;
  3. Resource Owner Password Credentials(資源所有者密碼):直接通過用戶名和密碼獲得授權(quán)腿宰,這種適用于高度信任的應(yīng)用呕诉,因?yàn)樾枰斎胗脩裘兔艽a,安全泄露風(fēng)險高吃度;
  4. **Client Credentials(客戶端模式) **:這是無用戶操作模式甩挫,適用于機(jī)器對機(jī)器的對接,沒有用戶干預(yù)的應(yīng)用椿每,如后臺任務(wù)調(diào)度應(yīng)用伊者,采集數(shù)據(jù)應(yīng)用等;
  5. 混合模式:以上四種的組合间护。

其他理論先不說了亦渗,我們邊擼碼邊聊,這樣記憶深刻一點(diǎn)汁尺,這里就從最簡單的Client Credentials開始:

Client Credentials 客戶端授權(quán)模式

客戶端模式?jīng)]有用戶法精,就只是單純的機(jī)器對機(jī)器的交互,大概的流程如下:

image-20201230210937580

流程簡要說明:

  1. 首先客戶端帶上憑據(jù)向授權(quán)服務(wù)器獲取AccessToken痴突,這里的客戶端憑據(jù)是提前在授權(quán)服務(wù)器上備案過的搂蜓;
  2. 授權(quán)服務(wù)器驗(yàn)證客戶端憑據(jù),成功之后直接返回AccessToken辽装;
  3. 客戶端在帶上AccessToken訪問資源服務(wù)器帮碰;
  4. 資源服務(wù)器正常返回結(jié)果,如果沒有AccessToken是不能訪問受保護(hù)資源的拾积;

來殉挽,結(jié)合流程看看代碼怎么實(shí)現(xiàn),一步一步來:

>>>先創(chuàng)建API項(xiàng)目---資源服務(wù)器
  1. 創(chuàng)建一個OrderController拓巧,并在里面新增一個Orders 接口斯碌,接口沒有進(jìn)行保護(hù);

    image-20201231105706789
  2. 接口沒有進(jìn)行保護(hù)玲销,可以任意訪問输拇,如下:

    image-20201231105517893
>>>再創(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ù),如下:

  1. 新創(chuàng)建一個API項(xiàng)目逛裤,并引入IdentityServer4包瘩绒,并在內(nèi)存中模擬相關(guān)數(shù)據(jù),方便測試带族;

    image-20201231123450257

    術(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;

  2. 模擬數(shù)據(jù)準(zhǔn)備好了壹堰,就在Startup中進(jìn)行對應(yīng)的注入和配置拭卿,并開啟中間件,如下:

    image-20201231124703423
  3. 這樣就初步完成授權(quán)服務(wù)器的搭建贱纠,這里監(jiān)聽的端口改為6100了峻厚,用Postman先來測測是否能正常獲取Token,如下:

    image-20201231133328069

    可能有新手小伙伴會問谆焊,咋知道是這個地址能獲取token的惠桃? 小伙伴可以在瀏覽器中輸入以下鏈接,即可看見授權(quán)服務(wù)器的相關(guān)信息(授權(quán)服務(wù)器地址+/.well-known/openid-configuration):

    image-20201231133558917
  4. 授權(quán)服務(wù)器已經(jīng)好了懊渡,準(zhǔn)備將資源服務(wù)器接入到授權(quán)服務(wù)器刽射,對API接口進(jìn)行保護(hù)(ApiDemo項(xiàng)目中),如下:

    image-20201231135258124

    注:ApiDemo項(xiàng)目中需要Microsoft.AspNetCore.Authentication.JwtBearer包剃执,因?yàn)轫?xiàng)目是基于.NetCore3.1的誓禁,所以這里引用的包版本為3.1.10。

  5. 然后在接口上面加上[Authorize]特性肾档,將接口保護(hù)起來摹恰,看運(yùn)行效果如下:

    image-20201231135953125
  6. 在Postman中測試,先獲取AccessToken怒见,然后將獲取的AccessToken加入到Header中請求資源服務(wù)器中受保護(hù)的API俗慈,如下:

    image-20201231140952036
>>>真實(shí)客戶端訪問受保護(hù)API---控制臺

建一個控制臺項(xiàng)目,具體步驟如圖:

image-20201231144413626

這里就不用文字說明步驟遣耍,小伙伴一邊看代碼闺阱,一邊看注釋,這樣應(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ù)器請求AccessToken
    var 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資源的HttpClient
    var apiClient = new HttpClient();
    // 7. 將獲取到的Token以Bearer的方案設(shè)置在請求頭中
    apiClient.SetBearerToken(tokenResp.AccessToken);
    // 8. 向資源服務(wù)器中請求受保護(hù)的API
    var 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ù)往下看↓↓↓

image-20201231152850521

假如指定的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)險有說過):

image-20201231154747613

總結(jié)

從這篇開始,后續(xù)會盡快更新學(xué)習(xí)分享团南,小伙伴們加入一起學(xué)習(xí)噪沙,一起討論。下一篇說說Resource Owner Password Credentials.

一個被程序搞丑的帥小伙已慢,關(guān)注"Code綜藝圈"曲聂,跟我一起學(xué)~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末霹购,一起剝皮案震驚了整個濱河市佑惠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖膜楷,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旭咽,死亡現(xiàn)場離奇詭異,居然都是意外死亡赌厅,警方通過查閱死者的電腦和手機(jī)穷绵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來特愿,“玉大人仲墨,你說我怎么就攤上這事∽嵴希” “怎么了目养?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長毒嫡。 經(jīng)常有香客問我癌蚁,道長,這世上最難降的妖魔是什么兜畸? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任努释,我火速辦了婚禮,結(jié)果婚禮上咬摇,老公的妹妹穿的比我還像新娘伐蒂。我一直安慰自己,他們只是感情好肛鹏,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布饿自。 她就那樣靜靜地躺著,像睡著了一般龄坪。 火紅的嫁衣襯著肌膚如雪昭雌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天健田,我揣著相機(jī)與錄音烛卧,去河邊找鬼。 笑死妓局,一個胖子當(dāng)著我的面吹牛总放,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播好爬,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼局雄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了存炮?” 一聲冷哼從身側(cè)響起炬搭,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蜈漓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宫盔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體融虽,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年灼芭,在試婚紗的時候發(fā)現(xiàn)自己被綠了有额。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片模叙。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡溉奕,死狀恐怖解幼,靈堂內(nèi)的尸體忽然破棺而出缎患,到底是詐尸還是另有隱情贯溅,我是刑警寧澤枕磁,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布呐粘,位于F島的核電站十偶,受9級特大地震影響热某,放射性物質(zhì)發(fā)生泄漏腻菇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一昔馋、第九天 我趴在偏房一處隱蔽的房頂上張望筹吐。 院中可真熱鬧,春花似錦秘遏、人聲如沸丘薛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洋侨。三九已至,卻和暖如春倦蚪,著一層夾襖步出監(jiān)牢的瞬間希坚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工陵且, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裁僧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓慕购,卻偏偏與公主長得像聊疲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沪悲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容