IdentityServer4 是Asp.net core的一箇中間件,用於添加符合OpenId Connect和OAuth2.0規範的終端到Asp.net Core應用。在這裏簡單介紹一下Openid和OAuth2.0。html
OpenId:用戶身份認證(Authentication )。當用戶(End User)在微信、Google等OpenId提供者(OpenID Provider)平臺註冊帳戶時會產生一個身份標識,這個身份標識就是OpenId,當用戶登陸第三方應用(Relying Part)時若是Relying Part支持OpenId登陸,會生成一個帶有重定向地址的Url跳至OpenId Provider平臺登陸界面,用戶登陸成功後,根據重定向地址帶着OpenId跳回Relying Part,標識着用戶身份認證成功,該用戶在OpenId Provider平臺有註冊。Relying Part根據OpenId自動註冊帳戶,至此身份認證結束。有時Relying Part須要從Openid Provider那獲取該用戶的更多信息或資源,OpenId Provider須要對Relying Part的請求進行受權管理,這時就用要到OAuth2.0。ios
OAuth2.0:用戶訪問受權(Authorization)。OAuth2.0是一個JWT(Json Web Token ,Json格式Web令牌)解決方案。其最終目的是給用戶一個包含加密令牌的JSON字符串,這個令牌內包含受權信息,決定了該用戶能夠訪問那些資源。OAuth2.0協議規定了4種取得令牌的方式,能夠參考這篇文章OAuth2.0的四種方式。json
Openid Connect:實際上就是將Openid與OAuth2.0結合起來,解決身份認證和身份受權的問題。後端
客戶端模式只對客戶端進行受權,不涉及到用戶信息。若是你的api須要提供到第三方應用,第三方應用本身作用戶受權,不須要用到你的用戶資源,就能夠用客戶端模式,只對客戶端進行受權訪問api資源。api
微軟提供了一些針對IdentityServer4的項目模板,在命令行中輸入」 dotnet new -i IdentityServer4.Templates「便可安裝,安裝好後能夠看到當前已安裝的項目模板,其中有一個"is4empty",其實就是一個asp.net core 應用裝了IdentityServer4包。在命令行中輸入:dotnet new is4empty -n Projectname 就會根據這個模板生成一個新項目。下圖是個人項目,一個api客戶端、一個mvc客戶端,一個identityserver4服務端,其中Api客戶端是受保護的Api資源,Mvc客戶端是第三方客戶端,用於訪問被保護的Api客戶端,能夠當作是任意後端程序。瀏覽器
public void ConfigureServices(IServiceCollection services) { //添加IdentityServer var builder = services.AddIdentityServer() //身份信息受權資源 .AddInMemoryIdentityResources(Config.GetIdentityResources()) //API訪問受權資源 .AddInMemoryApiResources(Config.GetApis()) //添加客戶端 .AddInMemoryClients(Config.GetClients()); if (Environment.IsDevelopment()) { builder.AddDeveloperSigningCredential(); } else { throw new Exception("need to configure key material"); } } public void Configure(IApplicationBuilder app) { if (Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //使用IdentityServer中間件 app.UseIdentityServer(); }
爲了能更好的查看調試日誌,使用窗口調試,能夠在Properties/launchSettings.json中能夠更改監聽地址,默認爲5000服務器
啓動項目後使用瀏覽器打開:http://localhost:5000/.well-known/openid-configuration。能夠看到identityserver4的discover說明。微信
1,添加ApiResource:修改IdentityServer項目的Config類的GetClients方法,添加一個api資源(ApiResource)。每一個被保護的API項目必需有對應一個ApiResource,一個ApiResource能夠有被多個API標識,客戶端請求令牌時根據ApiResource名稱決定是否有權限訪問這個API。mvc
public static IEnumerable<ApiResource> GetApis() { return new ApiResource[] { //secretapi:標識名稱,Secret Api:顯示名稱,能夠自定義 new ApiResource("secretapi","Secret Api") }; }
2,添加客戶端模式用戶:定義好ApiResouce後,再來添加一個客戶端,使得這個客戶端能夠訪問secretapi這個資源。修改Config類中的GetClients方法,添加一個用戶用於支持客戶端模式的請求。app
public static IEnumerable<Client> GetClients() { return new Client[] { new Client() { //客戶端Id ClientId="apiClientCd", //客戶端密碼 ClientSecrets={new Secret("apiSecret".Sha256()) }, //客戶端受權類型,ClientCredentials:客戶端憑證方式 AllowedGrantTypes=GrantTypes.ClientCredentials, //容許訪問的資源 AllowedScopes={ "secretapi" } } }; }
1,配置API項目監聽端口和調試方式
2,配置Api項目認證
IdentityApi.Startup.cs
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddAuthentication("Bearer").AddJwtBearer(r => { //認證地址 r.Authority = "http://localhost:5000"; //權限標識 r.Audience = "secretapi"; //是否必需HTTPS r.RequireHttpsMetadata = false; }); } // 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(); } else { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); //使用認證中間件 app.UseAuthentication(); app.UseMvcWithDefaultRoute(); }
3,添加接口:新建一個空的Api控制器(IdentityController),在這個控制器中添加一個Api:GetUserClaims
[ApiController] public class IdentityController : ControllerBase { [HttpGet] [Route("api/identity")] [Microsoft.AspNetCore.Authorization.Authorize] public object GetUserClaims() { return User.Claims.Select(r => new { r.Type, r.Value }); } }
這時GetUserClaims這個Api是訪問不了的,用PostMan訪問時返回401未認證狀態
要訪問上面那個受保護的Api,分爲2步,第一步從IdentityServer獲取token,第二步把這個token使用Bearer authorization 方式添加到Http請求頭。
1,在IdentityMvc項目訪問受保護的Api
IdentityMvc項目安裝一個Nuget包:IdentityModel,這個包對HttpClient對象有擴寫,封裝了一些IdentityServer的經常使用請求。修改IdentityServer的監聽端口爲5002,使用窗口調試。
在IdentityMvc的HomeController.cs新增一個控制器GetData
public async Task<IActionResult> GetData() { var client = new HttpClient(); var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000"); if (disco.IsError) return new JsonResult(new { err=disco.Error}); var token= await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest() { //獲取Token的地址 Address = disco.TokenEndpoint, //客戶端Id ClientId = "apiClientCd", //客戶端密碼 ClientSecret = "apiSecret", //要訪問的api資源 Scope = "secretapi" }); if (token.IsError) return new JsonResult(new { err = token.Error }); client.SetBearerToken(token.AccessToken); string data = await client.GetStringAsync("https://localhost:5001/api/identity"); JArray json = JArray.Parse(data); return new JsonResult(json); }
訪問https://localhost:5002/home/getdata能夠看到已經成功返回數據
2,使用原生HTTP請求訪問受保護的Api
獲取access_token:直接打開http://localhost:5000/.well-known/openid-configuration,找到token_endpoint節點
使用PostMan對該節點發送以下Post請求獲取access_token
訪問被保護的Api
因爲使用的是Bearer認證機制,因此添加一個名爲Authorization的Http請求頭,請求頭的內容是字符串「Bearer」+空格+獲取到的Token:Bearer Token