從上一篇關於 常見術語說明中,主要是對IdentityServer4的說明,以及其中涉及常見的術語的表述說明,包括對身份認證服務器、用戶、客戶端、資源以及各個令牌等進行對比區別說明。html
而在這一篇中,咱們將嘗試經過簡單的方式來搭一個咱們的IdentityServer受權服務器,熟悉IdentityServer4中搭建的流程以及將出現的問題。node
如下的項目示例都是基於IdentityServer4 4.x版本以上進行說明。git
4.x版本較以前3.x的版本都有一些變動,在本例中,若發現與3.x版本有變動的一些地方,都會進行記錄說明。github
創建一個空的Asp.Net Core項目 ,使用Empty空模板web
可經過命令行的方式算法
NuGet>Install-Package IdentityServer4 shell
經過包管理器方式數據庫
添加IdentityServer4包json
修改Configure方法,注入到容器c#
app.UseIdentityServer();
將服務注入到容器後,還須要對IdentityServce進行配置內容
- 哪些API須要Authorization Server進行資源保護
- 哪些Client可使用這個Authorization Server
- 哪些User能夠被這個AuthorizationServer識別並受權
- 哪些資源能夠指定做用域
這裏方便演示,直接以靜態化的形式展現,實際開發應用中,可結合數據庫或reidis緩存的數據持久化方式獲取。
創建配置內容文件 IdentityConfig.cs
(具體的 OpenID Connect 配置信息來源文件)
public class IdentityConfig { public static IEnumerable<IdentityResource> IdentityResources => new IdentityResource[] { new IdentityResources.OpenId(), new IdentityResources.Profile(), }; /// <summary> /// Authorization Server保護了哪些 API Scope(做用域) /// </summary> /// <returns></returns> public static IEnumerable<ApiScope> GetApiScopes() { return new[] { new ApiScope("ApiScope1", "ApiScope2") }; } /// <summary> /// 哪些客戶端 Client(應用) 可使用這個 Authorization Server /// </summary> /// <returns></returns> public static IEnumerable<Client> GetClients() { return new[] { new Client() { ClientId="YuanIdentity", ///客戶端的標識,要是唯一的 ClientSecrets=new []{new Secret("6KGqzUx6nfZZp0a4NH2xenWSJQWAT8la".Sha256())}, ////客戶端密碼,進行了加密 AllowedGrantTypes= GrantTypes.ClientCredentials, ////受權方式,這裏採用的是客戶端認證模式,只要ClientId,以及ClientSecrets正確便可訪問對應的AllowedScopes裏面的api資源 AllowedScopes=new[]{"ApiScope1" }, //定義這個客戶端能夠訪問的APi資源數組,上面只有一個api } }; } /// <summary> /// 哪些User能夠被這個AuthorizationServer識別並受權 /// </summary> /// <returns></returns> public static IEnumerable<TestUser> GetTestUsers() { return new[] { new TestUser { SubjectId="001", Username="i3yuan", Password="123456" } }; } }
注意,若是你的代碼沒問題,可是依然報錯,好比「無效的scope」等,就多是nuget包版本問題
在3.1.x 到 4.x 的變動中,
ApiResource
的Scope
正式獨立出來爲ApiScope
對象,區別ApiResource
和Scope
的關係,Scope
是屬於ApiResource
的一個屬性,能夠包含多個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") }; }
在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. 在學習 IdentityServer4 時熟悉的 InMemory 來講,
AddInMemoryApiResources
變爲了AddInMemoryApiScopes
這個 ApiScope2. 咱們如今是本地調試,能夠告訴identity server4在程序的運行時候對這項工做進行設定: AddDeveloperSigningCredential(),它默認會存到硬盤上的, 因此每次重啓服務不會破壞開發時的數據同步。這個方法只適合用於identity server4在單個機器運行, 若是是 production 你得使用AddSigningCredential()這個方法
以上操做完成後, 啓動項目,經過它的 .well-known 端點來訪問服務器的配置信息,在瀏覽器的地址欄中,輸入地址:http://localhost:5050/.well-known/openid-configuration,並回車。應該能夠看到以下的響應信息。
body參數 application/x-www-form-urlencoded (post)
須要對token進行簽名, 這意味着 identity server 須要一對public和private key。同時也是能夠由上圖的解析發現是須要一對公私key的。
考慮IdentityServer4須要進行管理查看,添加頁面管理界面
官方爲咱們提供了一個快速啓動的UI界面,咱們只須要下載下來便可,這裏有兩個方法:
一、直接從這個地址下來下載,拷貝到項目中,一共三個文件夾;// https://github.com/IdentityServer/IdentityServer4.Quickstart.UI 二、在當前文件夾中執行命令,自動下載; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/master/getmaster.ps1'))
下載完官方提供的默認UI界面後,會提供默認的三個目錄文件夾分別爲:Quickstart (控制器方法)、Views(視圖)、wwwroot (靜態文件)
配置中間件來使用靜態文件:
app.UseStaticFiles();
運行展現效果,啓動默認的地址以下:
運行項目後,能夠發現啓動默認的歡迎界面,看到對應的項目版本,咱們這裏用的是最新的IdentityServer4
版本爲4.1.1
,以及點擊 discovery document,能夠看到了咱們上邊說到的 token 獲取的接口地址 ,其中對應的端點地址信息。
經過它的 .well-known 端點來訪問服務器的配置信息,在瀏覽器的地址欄中,輸入地址:http://localhost:5050/.well-known/openid-configuration,並回車,能夠看到對應的響應信息。
在上文中,咱們經過手動搭建的方式,從一個空模板的搭建,到引用對應的Nuget包,安裝修改配置,並搭配了官方提供的UI界面,初步造成了一個簡易的IdentityServer4
初始化項目框架,這種一步步的構建項目的方式。
官方也給咱們提供了對應的快捷建立項目的模板,因此,若是你不想建立MVC項目,能夠用官方提供的模板方式進行建立初始化項目。
dotnet new -i IdentityServer4.Templates
在命令的輸出中,能夠看到已經安裝了多個關於 IdentityServer4 的模版
模板 | 簡稱 | 說明 |
---|---|---|
IdentityServer4 with AdminUI | is4admin | 這爲用戶、身份、客戶端和資源提供了一個基於web的管理界面.該社區版本旨在測試IdentityServer集成場景,而且僅限於本地主機:5000、SQLite、10個用戶和2個客戶端。社區版不適合生產應用。 |
IdentityServer4 with ASP.NET Core Identity | is4aspid | 添加使用ASP.NET標識進行用戶管理的基本IdentityServer。若是您自動啓動數據庫,您將獲得兩個用戶:Alice和bob--都帶有密碼Pass123$。檢查SeedData.cs文件。 |
IdentityServer4 Empty | is4empty | 在沒有UI的狀況下建立一個最小的IdentityServer4項目。 |
IdentityServer4 with Entity Framework Stores | is4ef | 添加使用實體框架進行配置和狀態管理的基本IdghtyServer。若是您啓動數據庫,您將得到一些基本的客戶端和資源註冊,請檢查SeedData.cs文件。 |
IdentityServer4 with In-Memory Stores and Test Users | is4inmem | 添加具備UI、測試用戶和示例客戶端和資源的基本IdentityServer。顯示內存中的代碼和JSON配置。 |
IdentityServer4 Quickstart UI (UI assets only) | is4ui | 將快速啓動UI添加到當前項目(例如,能夠在is4empty 的基礎上添加) |
這裏面最爲簡單的項目模版就是 IdentityServer4 with In-Memory Stores and Test Users
了,它簡稱爲 is4inmem
,咱們下面就使用它來建立項目。
dotnet new 模板名 -n 項目名稱
啓動項目後,
能夠看到項目的效果跟咱們以前一步步搭建的效果是同樣的,這說明咱們已經建立了第一個可運行的 IdentityServer4 服務器了。
JWT簽名算法中,通常有兩個選擇,一個採用HS256,另一個就是採用RS256。
簽名其實是一個加密的過程,生成一段標識(也是JWT的一部分)做爲接收方驗證信息是否被篡改的依據。
所以,在開發應用的時候啓用JWT時候,使用RS256更加安全,你能夠控制誰能使用什麼類型的密鑰。同時可讓服務端是惟一擁有私鑰的一方,不需共享私鑰。
生產環境(負載集羣)通常須要使用固定的證書籤名與驗籤,以確保重啓服務端或負載的時候 Token 都能驗籤經過。(不使用臨時證書)
#生成私鑰文件 openssl genrsa -out idsrv4.key 2048 #建立證書籤名請求文件 CSR(Certificate Signing Request),用於提交給證書頒發機構(即 Certification Authority (CA))即對證書籤名,申請一個數字證書。 openssl req -new -key idsrv4.key -out idsrv4.csr #生成自簽名證書(證書頒發機構(CA)簽名後的證書,由於本身作測試那麼證書的申請機構和頒發機構都是本身,crt 證書包含持有人的信息,持有人的公鑰,以及簽署者的簽名等信息。當用戶安裝了證書以後,便意味着信任了這份證書,同時擁有了其中的公鑰。) openssl x509 -req -days 365 -in idsrv4.csr -signkey idsrv4.key -out idsrv4.crt #自簽名證書與私匙合併成一個文件 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,這個password後面會用到。
拷貝生成的證書,放到認證/受權服務器項目中。(VS中配置文件設置文件始終複製),最後把證書路徑和密碼配置到 IdentityServer 中,由於咱們自簽名的證書是 PKCS12 (我的數字證書標準,Public Key Cryptography Standards #12) 標準包含私鑰與公鑰)標準,包含了公鑰和私鑰。
A、在appsetting.json
配置文件中添加以下:此處須要配置password,即生成證書的時候輸入的密碼。
{ "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、配置完後便可。咱們啓動IDS4項目便可生成加密的token。
OpenSSL 提取 pfx 證書公鑰與私鑰
提取pfx證書公鑰和私鑰 從pfx證書中提取密鑰信息,並轉換爲key格式(pfx使用pkcs12模式補足) 1. 提取密鑰對(若是pfx證書已加密,會提示輸入密碼) openssl pkcs12 -in idsrv4.pfx -nocerts -nodes -out idsrv4.key 2. 從密鑰對提取公鑰 openssl rsa -in idsrv4.key -pubout -out idsrv4_pub.key 3. 從密鑰對提取私鑰 openssl rsa -in idsrv4.key -out idsrv4_pri.key 4. 由於RSA算法使用的是 pkcs8 模式補足,須要對提取的私鑰進一步處理獲得最終私鑰 openssl pkcs8 -topk8 -inform PEM -in idsrv4_pri.key -outform PEM -nocrypt
注意:
將獲得的token在jwt.io 網站來認證一下,須要將 crt 公鑰、key私鑰複製到驗證中,發現認證ok,則說明實現防篡改。
後綴爲crt公鑰須要帶着 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE----- 一塊兒複製。
後綴爲key私鑰私鑰須要帶着 -----BEGIN RSA PRIVATE KEY----- 和 -----END RSA PRIVATE KEY----- 一塊兒複製。