.Net Core 3.1 IdentityServer4 入門篇
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算是完成了,希望能給小夥伴們帶來一些幫助!
鑑於本人也是剛接觸這個框架不久,可能有些知識理解有誤,如有不正之處,敬請指正!