IdentityServer4在Asp.Net Core中的應用(一)
IdentityServer4是一套身份授權以及訪問控制的解決方案,專註於幫助使用.Net 技術的公司為現代應用程序建立標識和訪問控制解決方案,包括單點登錄、身份管理、授權和API安全。
下面我將具體介紹如何在.Net Core中實現OAuth授權,從最簡單的授權模式開始,在上一篇對OAuth2.0的詳細描述中,在客戶端模式中,我們說它在嚴格意義上講是不存在授權的問題,我們再來看下它的授權流程:
客戶端在向授權服務器申請令牌後,授權服務器直接將令牌返回給了客戶端,這個過程不需要其他角色的任何操作,只是客戶端和授權服務器的交互。我們結合具體的示例來進一步了解這個過程。
操作系統:Mac OS
開發工具:VS Code
調試工具:Postman
開發框架:.Net Core 2.0
在具體示例實現之前,先說一下在VS Code我們會用到的插件,以方便我們的開發,畢竟VS Code沒有我們宇宙第一IDE-Visual Studio那麽強大,但是也是目前為止最好用的編輯器,它提供了各式各樣的插件,幾乎滿足我們所有的開發需求。在這裏我們用到的一個插件叫做Nuget Package Manager,這個插件可以方便我們使用快捷鍵對Nuget包進行管理。
接下來我們首先創建一個授權服務器的項目,打開VS Code使用控制臺,創建一個WebApi的項目,使用命令:
dotnet new WebApi -n IdentityServer4.Server
創建完成後,我們可以啟動查看我們的項目,run一下:
這樣我們的項目是可以運行成功的,下面我們進行添加IdentitServer4包的引用,在我們安裝了Nuget Package Manager後,我們可以快速的使用快捷鍵,在Mac系統中使用command+p,然後輸入">",然後輸入Nuget... (註意一定要切換到當前的項目下)會出現以下提示:
選擇第一個選項添加Package:
按回車,選擇IdentityServer4最新版本的安裝,這裏是2.1.3,安裝完後,我們在StartUp中添加IdentityServer4的引用,並使用AddIdentityServer()方法在依賴註入系統中註冊IdentityServer,當然這裏我們也可以等到添加完配置類後再進行操作。我們先添加一個配置類,叫做Config.cs,首先定義一個管道(Scope),指定我們所保護Api資源,該方法返回一個ApiResources集合,具體代碼如下:new ApiResource("api","UsersApi"),第一個參數為Api的名稱,第二個參數為顯示的名稱:
下一步進行客戶端註冊,定義給客戶端可以返回的資源,即允許哪個Scope定義,代碼如下:
下面我們將該配置註入到系統中,
AddDeveloperSigningCredential(),是一種RSA證書加密方式,它會生成一個tempkey.rsa證書文件,項目每次啟動時,會檢查項目根目錄是否存在該證書文件,若不存在,則會生成該文件,否則會繼續使用該證書文件。後面依次將ApiResources和Clients添加到內存中。
下一步是配置IdentityServer4的管道,在Configure裏面添加,app.UseIdentityServer(),在這裏我們用不到mvc,將app.UseMvc()註釋掉即可。下面我們運行我們的項目,當然直接訪問http://localhost:5000是看不到任何東西的,在這裏我們使用一個固定的地址http://localhost:5000/.well-known/openid-configuration,可以查看IdentityServer4的配置信息,運行格式化後內容如下:
{ "issuer": "http://localhost:5000", "jwks_uri": "http://localhost:5000/.well-known/openid-configuration/jwks", "authorization_endpoint": "http://localhost:5000/connect/authorize", "token_endpoint": "http://localhost:5000/connect/token", "userinfo_endpoint": "http://localhost:5000/connect/userinfo", "end_session_endpoint": "http://localhost:5000/connect/endsession", "check_session_iframe": "http://localhost:5000/connect/checksession", "revocation_endpoint": "http://localhost:5000/connect/revocation", "introspection_endpoint": "http://localhost:5000/connect/introspect", "frontchannel_logout_supported": true, "frontchannel_logout_session_supported": true, "backchannel_logout_supported": true, "backchannel_logout_session_supported": true, "scopes_supported": [ "api", "offline_access" ], "claims_supported": [], "grant_types_supported": [ "authorization_code", "client_credentials", "refresh_token", "implicit" ], "response_types_supported": [ "code", "token", "id_token", "id_token token", "code id_token", "code token", "code id_token token" ], "response_modes_supported": [ "form_post", "query", "fragment" ], "token_endpoint_auth_methods_supported": [ "client_secret_basic", "client_secret_post" ], "subject_types_supported": [ "public" ], "id_token_signing_alg_values_supported": [ "RS256" ], "code_challenge_methods_supported": [ "plain", "S256" ] }這表明我們的IdentityServer已經配置成功,下面我們借助Postman模擬發起獲取令牌請求,我們使用token_point的地址:http://localhost:5000/connect/token獲取acces token,Postman配置如下:
上面指定的3個參數都是客戶端模式需要指定的參數,下面就是我們請求到的access token。接著我們創建一個Api,去調用我們的授權服務器進行授權,重復上面的步驟,創建一個WebApi項目,不再贅述,直接去配置調用授權服務器,這個項目只是一個Api的項目,不需要完整的IdentityServer4的引用,只引用一個IdentityServer4.AccessTokenValidation包就可以了。在授權服務器中我們已經占用5000端口,所以在這個項目中我們指定為5001端口,在Program.cs裏面指定5001端口,添加.UseUrls("http://localhost:5001"):
在ValuesController裏面添加 Microsoft.AspNetCore.Authorization的引用,並添加[Authorize]標簽,即要求該Controller要通過授權才可以訪問,
下面我們在StartUp.cs裏面去配置授權服務:
接著我們分別啟動授權服務器和Api,我們運行Api,訪問:http://localhost:5001/api/values ,訪問結果如下:
提示Http Error 401 ,在狀態碼中401即未授權,我們把它拿到Postman中運行:
我們在Headers中指定Authorization 模式為Bearer,狀態401 未授權,這個結果也是我們意料中的結果了,因為我們並未獲取到令牌,我們繼續使用Postman模擬獲取到access token,
我們將獲取到的access_token放到Api的Headers裏面:
註意令牌與Bearer中間加空格,接下來繼續請求:
這樣我們就拿到了Api裏面要獲取的值了,到這裏我們使用Postman驗證了我們的結果,下面我們再創建一個第三方應用,去請求我們的Api資源,繼續了解我們的授權流程,客戶端我使用控制臺程序進行測試。
我們繼續使用命令行創建第三方應用,名稱為ThirdPartyApplication,IdentityServer4有一個專門專門為客戶端程序用的Nuget包,叫做IdentityModel,我們還是通過快捷鍵添加Nuget Package,下面直接上代碼,必要說明會在代碼中直接註釋:
using System; using System.Net.Http; using IdentityModel; using IdentityModel.Client; namespace ThirdPartyApplication { class Program { static void Main(string[] args) { //請求授權服務器 var diso=DiscoveryClient.GetAsync("http://localhost:5000").Result; if(diso.IsError) { Console.WriteLine(diso.Error); } //授權服務器根據客戶端發來的請求返回令牌 var tokenClient=new TokenClient(diso.TokenEndpoint,"Client","secret"); var tokenResponse=tokenClient.RequestClientCredentialsAsync("api").Result; if(tokenResponse.IsError) { Console.WriteLine(tokenResponse.Error); } //如果成功,則打印輸出返回的令牌信息 else { Console.WriteLine(tokenResponse.Json); } //創建HttpClient對象 var httpClient=new HttpClient(); //設置Authorization的Value值 httpClient.SetBearerToken(tokenResponse.AccessToken); //根據授權服務器返回的令牌信息請求Api資源 var response= httpClient.GetAsync("http://localhost:5001/api/values").Result; //如果返回結果為成功,輸出Api資源的結果 if(response.IsSuccessStatusCode) { Console.WriteLine(response.Content.ReadAsStringAsync().Result); } } } }
下面輸出結果:
以上就是我們整個OAuth2.0授權模式中完整的客戶端授權模式了,以上流程簡化如下:
後面文章會繼續講解其他幾種授權模式的使用。各位,晚安。
掃描二維碼關註我的公眾號,共同學習,共同進步!
IdentityServer4在Asp.Net Core中的應用(一)