從壹開始 [ Ids4 ] 之二║ 基礎知識集合 & 項目搭建一


前言

哈嘍大家又見面啦,感覺好久沒更新了,這幾天看了一本書《解憂雜貨鋪》,嗯挺好的,推薦一下😀。

 

不過還是要學習了,這些天簡單的看了看 Id4 的資料,才發現原來關於 Id4 的系列文章真是數不勝數,而且還有很多的深度好文章, 說的灰常之詳細,所以一度打消了我寫這一系列的沖動和信心,不過還是有一部分的小伙伴還沒有學習過,所以我決定我以后就把 IdentityServer4 的基礎概念知識點,就少寫些,重點寫如何在項目中使用吧,本文的知識點,簡單過一遍,腦子里有這個東西就行了,再以后的開發中,多動手就知道了,特別簡單的,這里說明一下,在以前的Blog.Core 系列中,有關 JWT 的知識,我單拎出來一個小Demo,有不懂的可以下載看看(https://github.com/anjoy8/BlogArti/tree/master/Blog.Core_JWT)。

 

零、今天要完成紅色的部分

 

 

 

一、常見術語

 

1、身份認證服務器(IdentityServer)

IdentityServer 是基於OpenID Connect協議標准的身份認證和授權程序,它實現了OpenID Connect 和 OAuth 2.0 協議。

同樣的角色,不同的文檔使用不同的術語。在有些文檔中,它(IdentityServer)可能會被叫做安全令牌服務器(security token service)、身份提供者(identity provider)、授權服務器(authorization server)、 標識提供方((IP-STS,什么是IP-STS)等等。

但是它們都是一樣的,都是向客戶端發送安全令牌(security token),

IdentityServer有許多功能:

  • 保護你的資源
  • 使用本地帳戶或通過外部身份提供程序對用戶進行身份驗證
  • 提供會話管理和單點登錄
  • 管理和驗證客戶機
  • 向客戶發出標識和訪問令牌
  • 驗證令牌

 

2、用戶(User)

用戶是使用已注冊的客戶端(指在id4中已經注冊)訪問資源的人。

 

3、客戶端(Client)

客戶端就是從identityserver請求令牌的軟件(你可以理解為一個app即可),既可以通過身份認證令牌來驗證識別用戶身份,又可以通過授權令牌來訪問服務端的資源。但是客戶端首先必須在申請令牌前已經在identityserver服務中注冊過。

實際客戶端不僅可以是Web應用程序,app或桌面應用程序(你就理解為pc端的軟件即可),SPA,服務器進程等。

 

4、資源(Resources)

資源就是你想用identityserver保護的東東,可以是用戶的身份數據或者api資源。
每一個資源都有一個唯一的名稱,客戶端使用這個唯一的名稱來確定想訪問哪一個資源(在訪問之前,實際identityserver服務端已經配置好了哪個客戶端可以訪問哪個資源,所以你不必理解為客戶端只要指定名稱他們就可以隨便訪問任何一個資源)。

用戶的身份信息實際由一組claim組成,例如姓名或者郵件都會包含在身份信息中(將來通過identityserver校驗后都會返回給被調用的客戶端)。

API資源就是客戶端想要調用的功能(通常以json或xml的格式返回給客戶端,例如webapi,wcf,webservice),通常通過webapi來建立模型,但是不一定是webapi,我剛才已經強調可以使其他類型的格式,這個要看具體的使用場景了。

 

 

5、訪問令牌(Access Token)

訪問令牌允許訪問API資源。 客戶端請求訪問令牌並將其轉發到API。 訪問令牌包含有關客戶端和用戶的信息(如果存在)。 API使用該信息來授權訪問其數據。

訪問令牌允許客戶端訪問某個 API 資源。客戶端請求到訪問令牌,然后使用這個令牌來訪問 API資源。訪問令牌包含了客戶端和用戶(如果有的話,這取決於業務是否需要,但通常不必要)的相關信息,API通過這些令牌信息來授予客戶端的數據訪問權限。

OAuth2提供了Access Token來解決授權第三方客戶端訪問受保護資源的問題;

 

 

 

6、身份令牌(Id Token)

上面提到過OIDC對OAuth2最主要的擴展就是提供了ID Token。ID Token是一個安全令牌,是一個授權服務器提供的包含用戶信息(由一組Cliams構成以及其他輔助的Cliams)的JWT格式的數據結構。ID Token的主要構成部分如下(使用OAuth2流程的OIDC)。

  1. iss = Issuer Identifier:必須。提供認證信息者的唯一標識。一般是一個https的url(不包含querystring和fragment部分)。
  2. sub = Subject Identifier:必須。iss提供的EU的標識,在iss范圍內唯一。它會被RP用來標識唯一的用戶。最長為255個ASCII個字符。
  3. aud = Audience(s):必須。標識ID Token的受眾。必須包含OAuth2的client_id。
  4. exp = Expiration time:必須。過期時間,超過此時間的ID Token會作廢不再被驗證通過。
  5. iat = Issued At Time:必須。JWT的構建的時間。
  6. auth_time = AuthenticationTime:EU完成認證的時間。如果RP發送AuthN請求的時候攜帶max_age的參數,則此Claim是必須的。
  7. nonce:RP發送請求的時候提供的隨機字符串,用來減緩重放攻擊,也可以來關聯ID Token和RP本身的Session信息。
  8. acr = Authentication Context Class Reference:可選。表示一個認證上下文引用值,可以用來標識認證上下文類。
  9. amr = Authentication Methods References:可選。表示一組認證方法。
  10. azp = Authorized party:可選。結合aud使用。只有在被認證的一方和受眾(aud)不一致時才使用此值,一般情況下很少使用。

ID Token通常情況下還會包含其他的Claims(畢竟上述claim中只有sub是和EU相關的,這在一般情況下是不夠的,必須還需要EU的用戶名,頭像等其他的資料,OIDC提供了一組公共的cliams,請移步這里http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)。另外ID Token必須使用JWS進行簽名和JWE加密,從而提供認證的完整性、不可否認性以及可選的保密性。

 

OIDC在這個基礎上提供了ID Token來解決第三方客戶端標識用戶身份認證的問題。OIDC的核心在於在OAuth2的授權流程中,一並提供用戶的身份認證信息(ID Token)給到第三方客戶端,ID Token使用JWT格式來包裝,得益於JWT(JSON Web Token)的自包含性,緊湊性以及防篡改機制,使得ID Token可以安全的傳遞給第三方客戶端程序並且容易被驗證。此外還提供了UserInfo的接口,用戶獲取用戶的更完整的信息。

簡而言之ID Token就是JWT格式的數據,包含一個人類用戶的身份認證的信息,一個ID Token的例子如下:

 

 

 

7、刷新令牌(Refresh Token)

access token 是客戶端訪問資源服務器的令牌。擁有這個令牌代表着得到用戶的授權。然而,這個授權應該是臨時的,有一定有效期。這是因為,access token 在使用的過程中可能會泄露。給 access token 限定一個較短的有效期可以降低因 access token 泄露而帶來的風險。

  然而引入了有效期之后,客戶端使用起來就不那么方便了。每當 access token 過期,客戶端就必須重新向用戶索要授權。這樣用戶可能每隔幾天,甚至每天都需要進行授權操作。這是一件非常影響用戶體驗的事情。希望有一種方法,可以避免這種情況。

  於是 Oauth2.0 引入了 refresh token 機制。refresh token 的作用是用來刷新 access token。鑒權服務器提供一個刷新接口,例如:

  http://xxx.xxx.com/refresh?refreshtoken=&client_id=

  傳入 refresh token 和 client_id,鑒權服務器驗證通過后,返回一個新的 access token。為了安全,Oauth2.0 引入了兩個措施:

  1,Oauth2.0 要求,refresh token 一定是保存在客戶端的服務器上的,而絕不能存放在狹義的客戶端(例如移動 app、PC端軟件) 上。調用 refresh 接口的時候,一定是從服務器到服務器的訪問;

  2,Oauth2.0 引入了 client_secret 機制。即每一個 client_id 都對應一個 client_secret。這個 client_secret 會在客戶端申請 client_id 時,隨 client_id 一起分配給客戶端。客戶端必須把 client_secret 妥善保管在服務器上,決不能泄露。刷新 access token 時,需要驗證這個 client_secret。

  於是,實際上的刷新接口應該是類似這樣的:

  http://xxx.xxx.com/refresh?refreshtoken=&client_id=&client_secret=

  以上就是 refresh token 機制。refresh token 的有效期非常長,會在用戶授權時,隨 access token 一起重定向到回調 url,傳遞給客戶端。

 

 

二、 OAuth 2.0 和 OpenID Connect

1、什么是OAuth2.0 ?

OAuth(開放授權)是一個開放標准,允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯系人列表),而無需將用戶名和密碼提供給第三方應用。就比如我用QQ登錄博客園,那博客園(第三方應用)的昵稱就可以是我的QQ(某網站)昵稱,它獲取到了我的QQ昵稱,並存到了博客園的數據庫,我以后就一直可以使用QQ來登錄博客園,但是博客園卻不知道我QQ的用戶名和密碼。

OAuth 允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。每一個令牌授權一個特定的網站(例如,視頻編輯網站)在特定的時段(例如,接下來的 2 小時內)內訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,OAuth 讓用戶可以授權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非所有內容。

OAuth 2.0 四種授權模式:

 

授權碼模式(authorization code)

簡化模式(implicit grant type) 

密碼模式(resource owner password credentials)

客戶端模式(Client Credentials Grant)

  

具體的概念和如何使用不細說,以后會分四篇文章詳細說明,今天主要是基礎知識和項目的搭建。

 

2、什么是 OpenID Connect ?

簡單來說:

  • OpenID Connect是基於OAuth 2.0規范族的可互操作的身份驗證協議。它使用簡單的REST / JSON消息流來實現,和之前任何一種身份認證協議相比,開發者可以輕松集成。
  • OpenID Connect允許開發者驗證跨網站和應用的用戶,而無需擁有和管理密碼文件。
  • OpenID Connect允許所有類型的客戶,包括基於瀏覽器的JavaScript和本機移動應用程序,啟動登錄流動和接收可驗證斷言對登錄用戶的身份。

進一步來說:
  • OpenID Connect是OAuth 2.0協議之上的簡單身份層,用 API 進行身份交互的框架,允許客戶端根據授權服務器的認證結果最終確認用戶的身份,以及獲取基本的用戶信息
  • 它支持包括Web、移動、JavaScript在內的所有客戶端類型;
  • 它是可擴展的協議,允許你使用某些可選功能,如身份數據加密、OpenID提供商發現、會話管理;
OpenID Connect vs OpenID 2.0:OpenID Connect完成很多與OpenID 2.0相同的任務,是API-friendly,定義了可選的簽名和加密的機制;OAuth 1.0和OpenID 2.0的集成需要擴展,而OpenID Connect協議本身就建立在OAuth 2.0之上。

為什么開發者要使用OpenID Connect?
因為它很簡單,可靠,安全,並讓他們擺脫困難和危險的存儲和管理別人的密碼。也有好處,它讓用戶的生活更容易在網站注冊和注冊從而減少遺棄。

 

3、JWT 和 OAuth2.0 的比較

要比較JWT和OAuth2,首先要明白一點就是,這兩個根本沒有可比性,是兩個完全不同的東西。

  • JWT是一種認證協議
    JWT提供了一種用於發布接入令牌(Access Token),並對發布的簽名接入令牌進行驗證的方法。 令牌(Token)本身包含了一系列聲明,應用程序可以根據這些聲明限制用戶對資源的訪問。

  • OAuth2是一種授權框架
    另一方面,OAuth2是一種授權框架,提供了一套詳細的授權機制(指導)。用戶或應用可以通過公開的或私有的設置,授權第三方應用訪問特定資源

既然 JWT和OAuth2.0 沒有可比性,為什么還要把這兩個放在一起說呢?實際中確實會有很多人拿 JWT和OAuth2.0 作比較。很多情況下,在討論OAuth2的實現時,會把JSON Web Token作為一種認證機制使用。這也是為什么他們會經常一起出現。

 

4、OpenID 是怎么認證用戶的?

一個網站如果想要接入 OpenID 認證是非常簡單的,不需要創建應用,不需要 App Key ,不需要 Secret ,只需要將用戶導向 OpenID Provider 的 Entry 並帶上 Callback ,用戶只要同意提供信息,你就可以拿到這個用戶的“唯一標識”。

請注意這里我使用了“唯一標識”這種說法,因為對於網站來說,OpenID Provider 提供的既不是用戶的 UID ,也不是用戶的 E-Mail ,比如 Google 在默認情況下提供的就是一個幾十位長的字符串,這個字符串是隨機生成的,第三方網站無法從中獲得用戶的任何私人信息。這么說可能很抽象,舉個例子:

比如我用 Google 的 OpenID 服務登錄 xxx.com , xxx.com 先把我導向 Google 的授權頁面,我使用 Google 帳號 test@gmail.com 登錄並同意后,頁面跳回 xxx.com , xxx.com 拿到了我的“唯一標識”,這個唯一標識可能是 cdxxxxxxxaaf6b73bcb04a1 ,xxx.com 從這個字符串里無法獲得任何 test@gmail.com 的個人信息(甚至連郵箱地址也不知道), xxx.com 只知道以后只要使用谷歌登錄並返回 cdxxxxxxxaaf6b73bcb04a1 這個標識符,那就是我在登錄。

顯而易見,OpenID 是專為登錄認證而生,它使用簡單,門檻很低,但是如果你想在認證過程中獲得用戶的其他信息(比如 E-Mail )就得多做一步了。

你這個時候可能就會問了,那有哪些網站使用的是 OpenID 登錄的呢,我簡單看了看,好像都是基於 OAuth 開發的,而且也看到了一個博問,是這么說的:

具體的咱們就不分析了,現在基本都是使用的 OAuth2.0 ,不過現在使用  Id4 是結合了 OAuth2.0 和 OpenID的。

 

5、OAuth 又是怎么認證用戶的?

 

與 OpenID 相比,網站想接入 OAuth 要稍微麻煩點,網站需要先創建應用,拿到 Key 和 Secret ,才能接入 Provider 。

OAuth 的授權過程並不是身份認證的過程,這一點需要特別清楚,網站走完 OAuth 流程並拿到用戶的授權 token 后還需要通過 token 調用相應的用戶信息接口才能獲得“唯一標識”,舉個例子:

我想通過新浪微博登錄 xxx.com ,xxx.com 要先把我 redirect 到新浪微博的授權頁面,我通過微博帳號登錄並授權后,頁面跳回 xxx.com ,xxx.com 拿到我的訪問 token 后還要再調用一個接口來獲得我的新浪會員 UID ,這個 UID 就是新浪用戶的“唯一標識”了。

可以看出,OAuth 相對於 OpenID 最大的區別就是,網站實際上是拿到了你的帳戶訪問權限繼而確認你的身份,這是一個安全隱患,因為網站在拿到你的“唯一標識”的同時還拿到了一把你的賬戶的 “臨時鑰匙”。至於網站會不會拿這把鑰匙“干壞事”,這個只有站長心里清楚。同時 OAuth 還比 OpenID 多了幾個額外的請求步驟,登錄所費時間一定是長於 OpenID 的。

 

6、OAuth和OpenID的區別

OAuth關注的是authorization;而OpenID側重的是authentication。從表面上看,這兩個英文單詞很容易混淆,但實際上,它們的含義有本質的區別:

  • authorization: n. 授權,認可;批准,委任
  • authentication: n. 證明;鑒定;證實

OAuth關注的是授權,即:“用戶能做什么”;而OpenID關注的是證明,即:“用戶是誰”。

 

OpenID是關於證明、證實身份(Authentication)的,好比火車站進站的時候拿出身份證和車票來看,比對是否同一個人。這是在回答「我是誰?這就是我」,是為了證實「這不是一個匿名的不可查的信息源頭」,因為匿名對象和信息對網絡服務商來說不好統計管理,也不利於產生價值。

OAuth 是關於授權、許可(Authorization)的,好比坐飛機過安檢的時候除了看身份證,還要求掏出兜里的東西,拿出包里的東西、手機等隨身物品以便檢查,這時就需要得到被檢查人的許可才行,被檢查人有權利扭頭就走,但要想登機,必須給予許可、掏出物品。這是在回答「我同意讓你對我進一步做些什么」,是為了在被授予權限的前提下,更多的獲取除了賬號密碼以外的個人信息,例如:聯系人通訊錄,郵箱號,電話號,地址,照片,聊天記錄,網絡發言、活動記錄,GPS 信息等等,來滿足用戶對服務的功能需要,或者「其他需要」。

 

//這里有個網友的說明,我感覺挺好的

 如今越來越多的網站,以及一些應用程序都開始使用第三方社交平台賬戶登錄,那這里就會涉及到安全性的問題,隱私的問題,你不能隨意來獲取我的資料,當然你來使用我的資料,你要經過用戶的同意,那這個用戶是不是我平台上,還是要來向我求證,那在這個過程中,實際上就出現了兩個過程,我們還是直接使用上次的例子來說明,比較直觀,CSDN使用QQ登錄,進入csdn的登錄頁,點擊使用QQ登錄:

   


       在進入到QQ登錄界面后,最開始是要請求認證,用戶輸入QQ號和密碼,點擊登錄,騰訊互聯會先進行驗證該用戶是否為我的用戶,如果是我的用戶,那么我會通知你(CSDN),他是我的用戶,你可以使用該賬戶登錄你的系統,這個過程就是認證(Authentication),認證就是證明你是誰,你是否是真實存在的,就好像,快遞員來給你送快遞,讓你出示你的身份證,他確定你是本人后,把快遞給你,這就是OpenID。

      而在QQ授權登錄下方,有兩給CheckBox復選框,可以允許CSDN獲得您的昵稱、頭像、性別,這是在認證之后的事了,在騰訊互聯你是我平台的用戶后,你可以自己選擇CSDN是否有權去獲取你的相關信息,當你勾選后,騰訊互聯就把你的這些基本信息給了CSDN,這個過程就是授權(Authorization),授權就是確定了你是誰后,又把屬於你的東西給了別人,猶如你向快遞員出示了身份證,然后你又把你房門的密碼給了他,並告訴他說,我把房門密碼給你,你幫我放到我客廳里吧。

  

 

7、OAuth 、OpenID 和 OpenID Connect 的關系

簡要而言,OIDC是一種安全機制,用於應用連接到身份認證服務器(Identity Service)獲取用戶信息,並將這些信息以安全可靠的方法返回給應用。

在最初,因為OpenID1/2經常和OAuth協議(一種授權協議)一起提及,所以二者經常被搞混。

  • OpenIDAuthentication,即認證,對用戶的身份進行認證,判斷其身份是否有效,也就是讓網站知道“你是你所聲稱的那個用戶”;
  • OAuthAuthorization,即授權,在已知用戶身份合法的情況下,經用戶授權來允許某些操作,也就是讓網站知道“你能被允許做那些事情”。
    由此可知,授權要在認證之后進行,只有確定用戶身份只有才能授權。

(身份驗證)+ OAuth 2.0 = OpenID Connect

OpenID Connect是“認證”和“授權”的結合,因為其基於OAuth協議,所以OpenID-Connect協議中也包含了client_idclient_secret還有redirect_uri等字段標識。這些信息被保存在“身份認證服務器”,以確保特定的客戶端收到的信息只來自於合法的應用平台。這樣做是目的是為了防止client_id泄露而造成的惡意網站發起的OIDC流程。

舉個例子。某個用戶使用Facebook應用“What online quiz best describes you?” ,該應用可以通過Facebook賬號登錄,則你可以在應用中發起請求到“身份認證服務器”(也就是Facebook的服務器)請求登錄。這時你會看到如下界面,詢問是否授權。

 

 在 OAuth 中,這些授權被稱為scope。OpenID-Connect也有自己特殊的scope--openid ,它必須在第一次請求“身份鑒別服務器”(Identity Provider,簡稱IDP)時發送過去。

 

 

三、創建基於EFCore的Idp項目 

 

你可以參考官方文檔:Docs » Welcome to IdentityServer4

 

1、建立空的NetCore MVC 項目

這個過程很簡單,因為你能看這個系列,證明你的 NetCore 功底已經很高了,至少中等,如果不會,請時光機回到我的第一個前后端分離系列。

1、創建一個新的ASP.NET Core項目;//可以使用命令行創建

2、選擇“空白”選項;//這里創建空的應用程序是為了后面方便引入UI界面

3、設置項目使用 kestrel 服務器,刪除IIS;

4、配置端口號;//我這里是5002,可自定義設置

 

 

1.1、使用官方提供的模板

如果你不想創建MVC項目,可以用官方提供的模板:

dotnet new -i IdentityServer4.Templates

dotnet new is4empty -n IdentityServer

 

 

 (這是我視頻教程中的導圖)

 

2、安裝並配置IdentityServer4

1、使用 nuget 添加 IdentityServer4 包;//當然你也可以使用命令: Install-Package IdentityServer4

2、配置認證服務中間件管道;//app.UseIdentityServer();

3、配置 IdentityServer 相關服務;

 

 注意,如果你的代碼某問題,但是依然報錯,比如“無效的scope”等,就是nuget包的問題,降級一下試試。

 

這里不僅要把 IdentityServer 注冊到容器中, 還要至少對其配置四點內容:

1、這個 Authorization Server 保護了哪些 API (資源);

2、哪些客戶端 Client(應用) 可以使用這個 Authorization Server;

3、指定可以使用 Authorization Server 授權的 Users(用戶);

4、指定作用域定義系統中的 IdentityResources 資源;//這個在以后說到 OpenId的時候再說,這里伏筆

首先在項目根目錄下,建立文件 InMemoryConfig.cs:

    public static class InMemoryConfig
    {
        // 這個 Authorization Server 保護了哪些 API (資源)
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new[]
            {
                    new ApiResource("blog.core.api", "Blog.Core API")
                };
        }
        // 哪些客戶端 Client(應用) 可以使用這個 Authorization Server
        public static IEnumerable<Client> GetClients()
        {
            return new[]
            {
                    new Client
                    {
                        ClientId = "blogvuejs",//定義客戶端 Id
                        ClientSecrets = new [] { new Secret("secret".Sha256()) },//Client用來獲取token
                        AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,//這里使用的是通過用戶名密碼和ClientCredentials來換取token的方式. ClientCredentials允許Client只使用ClientSecrets來獲取token. 這比較適合那種沒有用戶參與的api動作
                        AllowedScopes = new [] { "blog.core.api" }// 允許訪問的 API 資源
                    }
                };
        }
        // 指定可以使用 Authorization Server 授權的 Users(用戶)
        public static IEnumerable<TestUser> Users()
        {
            return new[]
            {
                    new TestUser
                    {
                        SubjectId = "1",
                        Username = "laozhang",
                        Password = "laozhang"
                    }
            };
        }
    }

 

GetApiResources:這里指定了name和display name, 以后api使用authorization server的時候, 這個name一定要一致, 否則就不好用的。

GetClients: Client的屬性太多了,基本的上邊已經注釋了

Users: 這里的內存用戶的類型是TestUser, 只適合學習和測試使用, 實際生產環境中還是需要使用數據庫來存儲用戶信息的, 例如接下來會使用asp.net core identity. TestUser的SubjectId是唯一標識.

 

 

然后回到 Startup 的 ConfigureServices 方法種:

我們需要對token進行簽名, 這意味着 identity server 需要一對public和private key。不過我們現在是本地調試,可以告訴identity server在程序的運行時候對這項工作進行設定: AddDeveloperSigningCredential(),它默認會存到硬盤上的, 所以每次重啟服務不會破壞開發時的數據同步。這個方法只適合用於identity server4在單個機器運行, 如果是 production 你得使用AddSigningCredential()這個方法:

    public class Startup
    {

        public IConfiguration Configuration { get; }
        public IHostingEnvironment Environment { get; }

        public Startup(IConfiguration configuration, IHostingEnvironment environment)
        {
            Configuration = configuration;
            Environment = environment;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseSuccessEvents = true;
            })
            // in-memory, code config
            .AddTestUsers(InMemoryConfig.Users().ToList())
            .AddInMemoryApiResources(InMemoryConfig.GetApiResources())
            .AddInMemoryClients(InMemoryConfig.GetClients());


            builder.AddDeveloperSigningCredential();

            if (Environment.IsDevelopment())
            {
                builder.AddDeveloperSigningCredential();
            }
            else
            {
                throw new Exception("need to configure key material");
            }

            services.AddAuthentication();//配置認證服務

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseIdentityServer();//啟動 IdentityServer
            app.UseMvcWithDefaultRoute();//啟動 MVC,這是netcore 2.2 的內容,3.0自行做響應的修改。
        }
    }

 

 
         

 

 
        

 

 

 

然后運行一下,在 Postman 中,嘗試通過上邊的用戶名密碼來獲取 Token :

 

 

 

 

 

是不是很熟悉,如果你用過 NetCore 的授權驗證的話,這些肯定都能看懂。

這里你一定很好奇,我是怎么知道要使用這個地址 localhost:5002/connect/token 來獲取Token的? ,一共還有多少個接口地址呢,要是有一個界面就好了。別着急往下看。IdentityServer4 官方已經考慮到了。

 

3、關於QuickStart UI

 官方為我們提供了一個快速啟動的UI界面,我們只需要下載下來即可,這里有兩個方法:

1、直接從這個地址下來下載,拷貝到項目中,一共三個文件夾;// https://github.com/IdentityServer/IdentityServer4.Quickstart.UI

2、在當前文件夾中執行命令,自動下載;

iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/master/getmaster.ps1'))

 

 

這樣我們的項目界面已經成功的獲取到了,除此之外,記得要配置中間件來使用靜態文件:

app.UseStaticFiles();

 

4、運行展示 

配置好后,F5運行,就可以看到了歡迎界面,點擊 discovery document,可以看到了我們上邊說到的 token 獲取的接口地址 localhost:5002/connect/token:

 (可能這個 Json 格式和你的不一樣,因為我安裝了chrome 的擴展插件了——JSONView)

 

5、配置 EFCore 連接到數據庫

因為篇幅的問題,這個下次再詳細說明,不過我的 GitHub 上已經寫好了,有需要的可以看看。

 

6、關於證書問題

這里信息暫時沒有用處,只是先作為一個備注記錄,待以后補充完善:

參考地址:https://www.cnblogs.com/guolianyu/p/9872661.html

 

1、HS256與RS256的區別

HS256 使用密鑰生成對稱的簽名,RS256 使用成非對稱進行簽名。簡單地說,HS256 必須與任何想要驗證 JWT的 客戶端或 API 共享秘密。

RS256 生成非對稱簽名,這意味着必須使用私鑰來簽簽名 JWT,並且必須使用對應的公鑰來驗證簽名。與對稱算法不同,使用 RS256 可以保證服務端是 JWT 的簽名者,因為服務端是唯一擁有私鑰的一方。這樣做將不再需要在許多應用程序之間共享私鑰

 

2、創建自簽名證書(操作步驟)

生產環境(負載集群)一般需要使用固定的證書簽名與驗簽,以確保重啟服務端或負載的時候 Token 都能驗簽通過。(不使用臨時證書)

那么證書如何生成請看下面分解步驟:

  第一種:使用OpenSSL生成證書,注:RSA加密證書長度要2048以上,否則服務運行會拋異常

復制代碼
#Linux系統生成證書:(推薦使用)
sudo yum install openssl (CentOS)
#生成私鑰文件 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 (包含公鑰)
#自簽名證書與私匙合並成一個文件(注:.pfx中可以加密碼保護,所以相對安全些) openssl pkcs12 -export -in idsrv4.crt -inkey idsrv4.key -out idsrv4.pfx (注:在生成的過程中會讓我們輸入Export Password)
復制代碼

 

 證書截圖如下:

 

  第二種:

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

 

生成如下:

 

3、證書生成之后就可進入VS2017中配置

拷貝生成的證書,放到認證/授權服務器項目中。(VS中配置文件設置文件始終復制),最后把證書路徑和密碼配置到 IdentityServer 中,因為我們自簽名的證書是 PKCS12 (個人數字證書標准,Public Key Cryptography Standards #12) 標准包含私鑰與公鑰)標准,包含了公鑰和私鑰。

 A、在appsetting.json 配置文件中添加如下:此處需要配置password,自定義即可。

 

B、在starup.cs中ConfigureServices方法中配置如下即可。

 

配置完后即可。我們啟動IDS4項目即可生成加密的token。

 

 

四、結語 

今天咱們主要通過一個小栗子,把我們的IdentityServer授權服務器搭建好了,並且做了相應配置,也獲取到了 Token ,是不是很簡單?感覺 Id4 也沒有我們想象的那么難是吧,關鍵就是上邊的Config.cs 中的三個配置,總結來說:

有哪些用戶可以通過哪些客戶端來訪問我們的哪些API保護資源

這要我們這些配置好了,自然我們也就可以使用 Id4 了,當然這個僅僅是獲取到了 Token,那如何連數據庫,如何應用在 API 資源服務器,又如何在客戶端配置呢,咱們下次再見咯。

五、Github

 

https://github.com/anjoy8/Blog.IdentityServer

 

-- END ---


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM