IdentityServer4是什么?
IdentityServer4 是為ASP.NET Core系列量身打造的一款基於 OpenID Connect 和 OAuth 2.0 認證框架。網上對於這個框架的介紹有很多,也很詳細,感興趣的小伙伴可以去多了解。
官方文檔:https://identityserver4.readthedocs.io/en/latest/
框架源碼:https://github.com/IdentityServer/IdentityServer4
整體部署
使用場景
-
- 瀏覽器與 Web 應用程序通信
- Web 應用程序與 Web API 通信(有時自己,有時代表用戶)
- 基於瀏覽器的應用程序與 Web API 通信
- 本機應用程序與 Web API 通信
- 基於服務器的應用程序與 Web API 通信
- Web API 與 Web API 通信(有時自己,有時代表用戶)
基本術語
IdentityServer(標識服務器)
標識服務器有許多作業和功能 - 包括:
-
- 保護您的資源
- 使用本地帳戶存儲或通過外部標識提供程序對用戶進行身份驗證
- 提供會話管理和單點登錄
- 管理和驗證客戶端
- 向客戶端頒發標識和訪問令牌
- 驗證令牌
Users(用戶)
用戶是使用注冊客戶端訪問資源的人們。
Client(客戶端)
客戶端用於驗證用戶(請求標識令牌)或訪問資源(請求訪問令牌)。客戶端必須首先注冊到標識服務器,然后才能請求令牌。
通常客戶端包括 Web 應用程序、本機移動或桌面應用程序、SCA、服務器進程等。
Resources(資源)
資源是您希望使用標識服務器保護的東西,一般是一些數據和API。
資源的名稱具有唯一性。
示例
本篇作為一個入門篇,我們就先從一個簡單的demo開始學習吧!
1.創建IdentityServer站點
用VS2019創建一個IdentityServer站點,選擇ASP.NET Core Web 應用程序,項目名稱自己定.
然后安裝項目的Nuget包管理器,安裝包:IdentityServer4
配置 Startup的ConfigureServices方法
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient(); services.AddIdentityServer().AddInMemoryApiScopes(new List<ApiScope>() { new ApiScope("api1","my api") }).AddInMemoryClients(new List<Client>() { new Client{ ClientId="my_client", AllowedGrantTypes=GrantTypes.ClientCredentials, ClientSecrets={ new Secret("aa123456bb".Sha256()) }, AllowedScopes={ "api1" } } }). AddDeveloperSigningCredential(); //使用固定的證書,防止IdentityServer4服務器重啟導致以往的token失效 //AddDeveloperSigningCredential(true, "tempkey.jwk"); }
配置Configure方法
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseIdentityServer(); //app.UseRouting(); //app.UseEndpoints(endpoints => //{ // endpoints.MapGet("/", async context => // { // await context.Response.WriteAsync("Hello World!"); // }); //}); }
啟動程序,在地址欄輸入https://localhost:5001/.well-known/openid-configuration,如果出現以下信息,則表示配置成功
2.創建API服務器(Resources)
添加nuget包:IdentityModel
配置 Startup的ConfigureServices方法
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient(); services.AddControllers(); services.AddAuthentication("Bearer").AddJwtBearer("Bearer", options => {
//identityserver4服務器地址 options.Authority = "https://localhost:5001"; options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false }; }); // adds an authorization policy to make sure the token is for scope 'api1' services.AddAuthorization(options => {
//定義授權策略 options.AddPolicy("ApiScope", policy => { policy.RequireAuthenticatedUser();
//這里的scope的值需要在identityserver4服務器上配置 policy.RequireClaim("scope", "api1"); }); }); }
配置Configure方法
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthentication();//認證 app.UseAuthorization();//授權 app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
創建一個api控制器,作為受保護的資源,在此控制器上配置授權策略,與ConfigureServices里配置的要一致
[Route("api/[controller]")] [ApiController] [Authorize("ApiScope")] public class HomeController : ControllerBase { [HttpGet] public string Get() { return "success"; } }
現在直接訪問api資源服務器,將返回401未授權狀態碼,表明api資源服務器此時已經受到了保護.
3.創建Client
我這里用的是WebApi,小伙伴們根據不同的需求可以選擇其他的客戶端.
直接上代碼
var client = new HttpClient();
//這里的https://localhost:5001為IdentityServer4服務器地址 var disco = await client.GetDiscoveryDocumentAsync("https://localhost:5001"); if (disco.IsError) { return Content(disco.Error); } var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest { Address = disco.TokenEndpoint, ClientId = "my_client", //需要在IdentityServer4服務器有定義 ClientSecret = "aa123456bb", //需要在IdentityServer4服務器有定義 Scope = "api1" //需要在IdentityServer4服務器有定義 }); if (tokenResponse.IsError) { return Content(tokenResponse.Error); } var apiClient = new HttpClient(); apiClient.SetBearerToken(tokenResponse.AccessToken);
//訪問受保護的API資源服務器 var content = await apiClient.GetStringAsync("https://localhost:15001/api/Home"); return Content(content);
至此,一個簡單的demo算是完成了,希望能給小伙伴們帶來一些幫助!
鑒於本人也是剛接觸這個框架不久,可能有些知識理解有誤,如有不正之處,敬請指正!