IdentityServer4系列 | 快速搭建简易项目
一 、前言
從上一篇關(guān)于 常見術(shù)語說明中,主要是對(duì)「IdentityServer4」的說明,以及其中涉及常見的術(shù)語的表述說明,包括對(duì)身份認(rèn)證服務(wù)器、用戶、客戶端、資源以及各個(gè)令牌等進(jìn)行對(duì)比區(qū)別說明。
而在這一篇中,我們將嘗試通過簡單的方式來搭一個(gè)我們的IdentityServer授權(quán)服務(wù)器,熟悉IdentityServer4中搭建的流程以及將出現(xiàn)的問題。
二、 搭建
?以下的項(xiàng)目示例都是基于IdentityServer4 「4.x」版本以上進(jìn)行說明。
4.x版本較之前3.x的版本都有一些變更,在本例中,若發(fā)現(xiàn)與3.x版本有變更的一些地方,都會(huì)進(jìn)行記錄說明。
?2.1.創(chuàng)建項(xiàng)目
建立一個(gè)空的Asp.Net Core項(xiàng)目 ,使用Empty空模板
2.2.安裝配置
2.2.1. 安裝程序包
可通過命令行的方式
?NuGet>Install-Package IdentityServer4
?通過包管理器方式
?添加IdentityServer4包
?
2.2.2. 配置管道
「修改Configure方法,注入到容器」
?app.UseIdentityServer();2.2.3. 配置內(nèi)容
「將服務(wù)注入到容器后,還需要對(duì)IdentityServce進(jìn)行配置內(nèi)容」
?哪些API需要Authorization Server進(jìn)行資源保護(hù)
哪些Client可以使用這個(gè)Authorization Server
哪些User可以被這個(gè)AuthorizationServer識(shí)別并授權(quán)
哪些資源可以指定作用域
這里方便演示,直接以靜態(tài)化的形式展示,實(shí)際開發(fā)應(yīng)用中,可結(jié)合數(shù)據(jù)庫或reidis緩存的數(shù)據(jù)持久化方式獲取。
建立配置內(nèi)容文件IdentityConfig.cs(具體的 OpenID Connect 配置信息來源文件)
????public?class?IdentityConfig{public?static?IEnumerable<IdentityResource>?IdentityResources?=>new?IdentityResource[]{new?IdentityResources.OpenId(),new?IdentityResources.Profile(),};///?<summary>///?Authorization?Server保護(hù)了哪些?API?Scope(作用域)///?</summary>///?<returns></returns>public?static?IEnumerable<ApiScope>?GetApiScopes(){return?new[]?{?new?ApiScope("ApiScope1",?"ApiScope2")?};}///?<summary>///?哪些客戶端?Client(應(yīng)用)?可以使用這個(gè)?Authorization?Server///?</summary>///?<returns></returns>public?static?IEnumerable<Client>?GetClients(){return?new[]{new?Client(){ClientId="YuanIdentity",?///客戶端的標(biāo)識(shí),要是惟一的ClientSecrets=new?[]{new?Secret("6KGqzUx6nfZZp0a4NH2xenWSJQWAT8la".Sha256())},?客戶端密碼,進(jìn)行了加密AllowedGrantTypes=?GrantTypes.ClientCredentials,?授權(quán)方式,這里采用的是客戶端認(rèn)證模式,只要ClientId,以及ClientSecrets正確即可訪問對(duì)應(yīng)的AllowedScopes里面的api資源AllowedScopes=new[]{"ApiScope1"?},?//定義這個(gè)客戶端可以訪問的APi資源數(shù)組,上面只有一個(gè)api}};}///?<summary>///?哪些User可以被這個(gè)AuthorizationServer識(shí)別并授權(quán)///?</summary>///?<returns></returns>public?static?IEnumerable<TestUser>?GetTestUsers(){return?new[]{new?TestUser{SubjectId="001",Username="i3yuan",Password="123456"}};}} ?「注意,如果你的代碼沒問題,但是依然報(bào)錯(cuò),比如“無效的scope”等,就可能是nuget包版本問題」
在3.1.x 到 4.x 的變更中,ApiResource 的 Scope 正式獨(dú)立出來為 ApiScope 對(duì)象,區(qū)別ApiResource 和 Scope的關(guān)系, Scope 是屬于ApiResource 的一個(gè)屬性,可以包含多個(gè)Scope。
所以
在3.x版本中
?public?static?IEnumerable<ApiResource>?GetApiResources(){return?new[]?{?new?ApiResource("ApiScope1",?"ApiScope2")?};}改成4.x版本為
public?static?IEnumerable<ApiScope>?GetApiScopes() {return?new[]?{?new?ApiScope("ApiScope1",?"ApiScope2")?}; } ?2.2.4. 添加配置服務(wù)
「在Startup.cs文件,ConfigureServices方法中」
????????public?void?ConfigureServices(IServiceCollection?services){services.AddMvc();services.AddIdentityServer().AddDeveloperSigningCredential().AddTestUsers(IdentityConfig.GetTestUsers().ToList()).AddInMemoryClients(IdentityConfig.GetClients()).AddInMemoryApiScopes(IdentityConfig.GetApiScopes());services.AddControllers();} ?「1. ?在學(xué)習(xí) IdentityServer4 時(shí)熟悉的 InMemory 來說,AddInMemoryApiResources 變?yōu)榱?AddInMemoryApiScopes ?這個(gè) ApiScope」
「2. ?我們現(xiàn)在是本地調(diào)試,可以告訴identity server4在程序的運(yùn)行時(shí)候?qū)@項(xiàng)工作進(jìn)行設(shè)定: AddDeveloperSigningCredential(),它默認(rèn)會(huì)存到硬盤上的, 所以每次重啟服務(wù)不會(huì)破壞開發(fā)時(shí)的數(shù)據(jù)同步。這個(gè)方法只適合用于identity server4在單個(gè)機(jī)器運(yùn)行, 如果是 production 你得使用AddSigningCredential()這個(gè)方法」
?以上操作完成后, 啟動(dòng)項(xiàng)目,通過它的 .well-known 端點(diǎn)來訪問服務(wù)器的配置信息,在瀏覽器的地址欄中,輸入地址:http://localhost:5050/.well-known/openid-configuration,并回車。應(yīng)該可以看到如下的響應(yīng)信息。
2.3. 獲取token
2.3.1. 啟動(dòng)項(xiàng)目
2.3.2. 測試訪問地址
?http://localhost:5050/connect/token
?body參數(shù) application/x-www-form-urlencoded (post)
2.3.3. Access_Token
?「需要對(duì)token進(jìn)行簽名, 這意味著 identity server 需要一對(duì)public和private key。同時(shí)也是可以由上圖的解析發(fā)現(xiàn)是需要一對(duì)公私key的。」
?三、UI界面
考慮IdentityServer4需要進(jìn)行管理查看,添加頁面管理界面
官方為我們提供了一個(gè)快速啟動(dòng)的UI界面,我們只需要下載下來即可,這里有兩個(gè)方法:
3.1. QuickStart UI界面
1、直接從這個(gè)地址下來下載,拷貝到項(xiàng)目中,一共三個(gè)文件夾;// https://github.com/IdentityServer/IdentityServer4.Quickstart.UI2、在當(dāng)前文件夾中執(zhí)行命令,自動(dòng)下載;iex?((New-Object?System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/master/getmaster.ps1'))3.2. 默認(rèn)目錄
下載完官方提供的默認(rèn)UI界面后,會(huì)提供默認(rèn)的三個(gè)目錄文件夾分別為:Quickstart (控制器方法)、Views(視圖)、wwwroot (靜態(tài)文件)
3.3. 修改配置
配置中間件來使用靜態(tài)文件:
app.UseStaticFiles();四、運(yùn)行
運(yùn)行展示效果,啟動(dòng)默認(rèn)的地址如下:
?http://localhost:5050
?運(yùn)行項(xiàng)目后,可以發(fā)現(xiàn)啟動(dòng)默認(rèn)的歡迎界面,看到對(duì)應(yīng)的項(xiàng)目版本,我們這里用的是最新的IdentityServer4版本為4.1.1 ,以及點(diǎn)擊 「discovery document」,可以看到了我們上邊說到的 token 獲取的接口地址 ,其中對(duì)應(yīng)的端點(diǎn)地址信息。
?「通過它的 .well-known 端點(diǎn)來訪問服務(wù)器的配置信息,在瀏覽器的地址欄中,輸入地址:http://localhost:5050/.well-known/openid-configuration,并回車,可以看到對(duì)應(yīng)的響應(yīng)信息。」
?五、模板
在上文中,我們通過手動(dòng)搭建的方式,從一個(gè)空模板的搭建,到引用對(duì)應(yīng)的Nuget包,安裝修改配置,并搭配了官方提供的UI界面,初步形成了一個(gè)簡易的IdentityServer4初始化項(xiàng)目框架,這種一步步的構(gòu)建項(xiàng)目的方式。
官方也給我們提供了對(duì)應(yīng)的快捷創(chuàng)建項(xiàng)目的模板,所以,如果你不想創(chuàng)建MVC項(xiàng)目,可以用官方提供的模板方式進(jìn)行創(chuàng)建初始化項(xiàng)目。
5.1. 安裝模板
dotnet?new?-i?IdentityServer4.Templates在命令的輸出中,可以看到已經(jīng)安裝了多個(gè)關(guān)于 IdentityServer4 的模版
| IdentityServer4 with AdminUI | is4admin | 這為用戶、身份、客戶端和資源提供了一個(gè)基于web的管理界面.該社區(qū)版本旨在測試IdentityServer集成場景,并且僅限于本地主機(jī):5000、SQLite、10個(gè)用戶和2個(gè)客戶端。社區(qū)版不適合生產(chǎn)應(yīng)用。 |
| IdentityServer4 with ASP.NET Core Identity | is4aspid | 添加使用ASP.NET標(biāo)識(shí)進(jìn)行用戶管理的基本IdentityServer。如果您自動(dòng)啟動(dòng)數(shù)據(jù)庫,您將得到兩個(gè)用戶:Alice和bob--都帶有密碼Pass123$。檢查SeedData.cs文件。 |
| IdentityServer4 Empty | is4empty | 在沒有UI的情況下創(chuàng)建一個(gè)最小的IdentityServer4項(xiàng)目。 |
| IdentityServer4 with Entity Framework Stores | is4ef | 添加使用實(shí)體框架進(jìn)行配置和狀態(tài)管理的基本IdghtyServer。如果您啟動(dòng)數(shù)據(jù)庫,您將獲得一些基本的客戶端和資源注冊(cè),請(qǐng)檢查SeedData.cs文件。 |
| IdentityServer4 with In-Memory Stores and Test Users | is4inmem | 添加具有UI、測試用戶和示例客戶端和資源的基本IdentityServer。顯示內(nèi)存中的代碼和JSON配置。 |
| IdentityServer4 Quickstart UI (UI assets only) | is4ui | 將快速啟動(dòng)UI添加到當(dāng)前項(xiàng)目(例如,可以在is4empty的基礎(chǔ)上添加) |
5.2. 選擇項(xiàng)目
這里面最為簡單的項(xiàng)目模版就是 IdentityServer4 with In-Memory Stores and Test Users 了,它簡稱為 is4inmem ,我們下面就使用它來創(chuàng)建項(xiàng)目。
dotnet?new?模板名?-n?項(xiàng)目名稱5.3. 啟動(dòng)應(yīng)用
啟動(dòng)項(xiàng)目后,
可以看到項(xiàng)目的效果跟我們之前一步步搭建的效果是一樣的,這說明我們已經(jīng)創(chuàng)建了第一個(gè)可運(yùn)行的 IdentityServer4 服務(wù)器了。
六、說明
6.1. HS256與RS256
JWT簽名算法中,一般有兩個(gè)選擇,一個(gè)采用HS256,另外一個(gè)就是采用RS256。
?「簽名實(shí)際上是一個(gè)加密的過程,生成一段標(biāo)識(shí)(也是JWT的一部分)作為接收方驗(yàn)證信息是否被篡改的依據(jù)。」
?「HS256」 使用密鑰生成「固定的簽名」,簡單地說,HS256 必須與任何想要驗(yàn)證 JWT的 客戶端或 API 「共享密鑰」,因此必須注意確保密鑰不被泄露。
「RS256」 生成「非對(duì)稱簽名」,這意味著必須使用私鑰來簽簽名 JWT,并且必須使用對(duì)應(yīng)的公鑰來驗(yàn)證簽名。與對(duì)稱算法不同,使用 RS256 可以保證服務(wù)端是 JWT 的簽名者,因?yàn)榉?wù)端是唯一擁有私鑰的一方。這樣做將不再需要在許多應(yīng)用程序之間共享私鑰。
因此,在開發(fā)應(yīng)用的時(shí)候啟用JWT時(shí)候,使用RS256更加安全,你可以控制誰能使用什么類型的密鑰。同時(shí)可以讓服務(wù)端是唯一擁有私鑰的一方,不需共享私鑰。
6.2 關(guān)于證書
生產(chǎn)環(huán)境(負(fù)載集群)一般需要使用固定的證書簽名與驗(yàn)簽,以確保重啟服務(wù)端或負(fù)載的時(shí)候 Token 都能驗(yàn)簽通過。(不使用臨時(shí)證書)
6.2.1 創(chuàng)建證書
#生成私鑰文件 openssl?genrsa?-out?idsrv4.key?2048 #創(chuàng)建證書簽名請(qǐng)求文件 CSR(Certificate Signing Request),用于提交給證書頒發(fā)機(jī)構(gòu)(即 Certification Authority (CA))即對(duì)證書簽名,申請(qǐng)一個(gè)數(shù)字證書。 openssl?req?-new?-key?idsrv4.key?-out?idsrv4.csr #生成自簽名證書(證書頒發(fā)機(jī)構(gòu)(CA)簽名后的證書,因?yàn)樽约鹤鰷y試那么證書的申請(qǐng)機(jī)構(gòu)和頒發(fā)機(jī)構(gòu)都是自己,crt 證書包含持有人的信息,持有人的公鑰,以及簽署者的簽名等信息。當(dāng)用戶安裝了證書之后,便意味著信任了這份證書,同時(shí)擁有了其中的公鑰。) openssl?x509?-req?-days?365?-in?idsrv4.csr?-signkey?idsrv4.key?-out?idsrv4.crt #自簽名證書與私匙合并成一個(gè)文件 openssl?pkcs12?-export?-in?idsrv4.crt?-inkey?idsrv4.key?-out?idsrv4.pfx或 openssl?req?-newkey?rsa:2048?-nodes?-keyout?idsrv4.key?-x509?-days?365?-out?idsrv4.cer openssl?pkcs12?-export?-in?idsrv4.cer?-inkey?idsrv4.key?-out?idsrv4.pfx中途提示讓你輸入Export Password,這個(gè)password后面會(huì)用到。
6.2.2 項(xiàng)目配置
拷貝生成的證書,放到認(rèn)證/授權(quán)服務(wù)器項(xiàng)目中。(VS中配置文件設(shè)置文件始終復(fù)制),最后把證書路徑和密碼配置到 IdentityServer 中,因?yàn)槲覀冏院灻淖C書是 PKCS12 (個(gè)人數(shù)字證書標(biāo)準(zhǔn),Public Key Cryptography Standards #12) 標(biāo)準(zhǔn)包含私鑰與公鑰)標(biāo)準(zhǔn),包含了公鑰和私鑰。
A、在appsetting.json 配置文件中添加如下:此處需要配置password,即生成證書的時(shí)候輸入的密碼。
{"Certificates":?{"CerPath":?"certificate\\idsrv4.pfx","Password":?"P@ssw0rd"} }?B、在starup.cs中ConfigureServices方法中配置如下即可。
var?basePath?=?PlatformServices.Default.Application.ApplicationBasePath; services.AddIdentityServer().AddSigningCredential(new?X509Certificate2( Path.Combine(basePath,Configuration["Certificates:CerPath"]), Configuration["Certificates:Password"]) )C、配置完后即可。我們啟動(dòng)IDS4項(xiàng)目即可生成加密的token。
6.2.3 提取補(bǔ)充
OpenSSL 提取 pfx 證書公鑰與私鑰
提取pfx證書公鑰和私鑰 從pfx證書中提取密鑰信息,并轉(zhuǎn)換為key格式(pfx使用pkcs12模式補(bǔ)足) 1.?提取密鑰對(duì)(如果pfx證書已加密,會(huì)提示輸入密碼) openssl?pkcs12?-in?idsrv4.pfx?-nocerts?-nodes?-out?idsrv4.key 2.?從密鑰對(duì)提取公鑰 openssl?rsa?-in?idsrv4.key?-pubout?-out?idsrv4_pub.key 3.?從密鑰對(duì)提取私鑰 openssl?rsa?-in??idsrv4.key?-out?idsrv4_pri.key 4.?因?yàn)镽SA算法使用的是?pkcs8?模式補(bǔ)足,需要對(duì)提取的私鑰進(jìn)一步處理得到最終私鑰 openssl?pkcs8?-topk8?-inform?PEM?-in?idsrv4_pri.key?-outform?PEM?-nocrypt ?「注意:」
將得到的token在jwt.io 網(wǎng)站來認(rèn)證一下,需要將 crt 公鑰、key私鑰復(fù)制到驗(yàn)證中,發(fā)現(xiàn)認(rèn)證ok,則說明實(shí)現(xiàn)防篡改。
后綴為crt公鑰需要帶著 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE----- 一起復(fù)制。后綴為key私鑰私鑰需要帶著 -----BEGIN RSA PRIVATE KEY----- 和 -----END RSA PRIVATE KEY----- 一起復(fù)制。
?七、總結(jié)
在本篇中我們通過手動(dòng)或者官方模板的方式簡易的實(shí)現(xiàn)了我們的IdentityServer授權(quán)服務(wù)器搭建,并做了相應(yīng)的配置和UI配置,實(shí)現(xiàn)了獲取Token方式。
對(duì)于相應(yīng)的配置我們需要注意的三個(gè)點(diǎn)就是,有哪些用戶(users)可以通過哪些客戶端(clents)來訪問我們的哪些API保護(hù)資源 (API)。
在后續(xù)會(huì)對(duì)其中的授權(quán)模式,數(shù)據(jù)庫持久化問題,以及如何應(yīng)用在API資源服務(wù)器中和配置在客戶端中,會(huì)進(jìn)一步說明。
如果有不對(duì)的或不理解的地方,希望大家可以多多指正,提出問題,一起討論,不斷學(xué)習(xí),共同進(jìn)步。
項(xiàng)目地址?
https://github.com/i3yuan/Yuan.IdentityServer4.Demo?
八、資料
IdentityServer4官方文檔
IdentiytServer4模板
IdentityServer4界面
總結(jié)
以上是生活随笔為你收集整理的IdentityServer4系列 | 快速搭建简易项目的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何写一段死锁代码
- 下一篇: 高并发项目Java是标配?.NET Co