Identity Server 4使用者端認證控制存取API

2022-07-10 21:01:14

專案原始碼:

連結:https://pan.baidu.com/s/1H3Y0ct8xgfVkgq4XsniqFA

提取碼:nzl3

一、說明

我們將定義一個api和要存取它的使用者端,使用者端將在identityser上請求存取令牌,並使用存取令牌呼叫api

二、專案結構與準備

1、建立專案QuickStartIdentityServer4的asp.net 3.1專案,埠號5001,NuGet: IdentityServer4

2、建立專案API的asp.net 3.1專案,埠號5000,NuGet: Microsoft.AspNetCore.Authentication.JwtBearer

3、建立專案Client控制檯專案(sp.net 3.1),模擬使用者端請求,NuGet: IdentityModel

 

 

 三、QuickStartIdentityServer4專案編碼

1、在QuickStartIdentityServer4專案中新增Config.cs檔案

public static class Config
    {
        // 定義api範圍
        public static IEnumerable<ApiScope> ApiScopes => new []
        {
            new ApiScope
            {
                Name="sample_api", // 範圍名稱,自定義
                DisplayName="Sample API" // 範圍顯示名稱,自定義
            }
        };

        // 定義使用者端
        public static IEnumerable<Client> Clients => new[]
        {
            new Client
            {
                ClientId="sample_client", // 使用者端id
                ClientSecrets =
                {
                    new Secret("sample_client_secret".Sha256()) // 使用者端祕鑰

                },
                AllowedGrantTypes=GrantTypes.ClientCredentials, //授權型別為使用者端
                AllowedScopes={ "sample_api" } // 設定該使用者端允許存取的api範圍
            }
        };

    }

2、在QuickStartIdentityServer4專案中Startup.cs檔案新增設定

public void ConfigureServices(IServiceCollection services)
        {
            var builder=services.AddIdentityServer();
            builder.AddDeveloperSigningCredential();
            builder.AddInMemoryApiScopes(Config.ApiScopes);
            builder.AddInMemoryClients(Config.Clients);
        }

3、存取http://localhost:5001/.well-known/openid-configuration

 

 

 4、存取http://localhost:5001/connect/token即可拿到令牌token

 

 該token是基於jwt,我們可以在jwt官網進行檢視驗證,如圖

 

 

 

四、API專案編碼

1、Startup.cs檔案設定

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

            // 新增JWT認證方案
            services.AddAuthentication("Bearer")
                     .AddJwtBearer("Bearer", option => {
                         // OIDC服務地址
                         option.Authority = "http://localhost:5001";
                         // 不使用Https
                         option.RequireHttpsMetadata = false;
                         // 設定JWT的驗證引數
                         option.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                         { 
                            // 因為使用的是api範圍存取,該引數需設定false
                            ValidateAudience=false
                         };

                     });
            // 新增api授權策略
            services.AddAuthorization(options => {
                // "ApiScope"為策略名稱
                options.AddPolicy("ApiScope", builder =>
                {
                    builder.RequireAuthenticatedUser();
                    // 鑑定claim是否存在
                    builder.RequireClaim("scope", "sample_api");
                });
            
            });

        }

        // 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
                //endpoints.MapControllers().RequireAuthorization("ApiScope");
            });
        }

2、新增控制器IdentityServerController並增加授權

[Route("IdentityServer")]
    [Authorize("ApiScope")]
    public class IdentityServerController : ControllerBase
    {
       
       public IActionResult Get()
        {
            return new JsonResult(from claim in User.Claims select new { claim.Type,claim.Value });
        }
    }

3、拿到token並請求api

 

 

五、Client專案模擬使用者端請求

internal class Program
    {
        static async Task Main(string[] args)
        {
            var client = new HttpClient();
            var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5001");
            if (disco.IsError)
            {
                Console.WriteLine(disco.Error);
                return;
            }

            var tokenResponse = await client.RequestClientCredentialsTokenAsync(
                    new ClientCredentialsTokenRequest
                    { 
                        Address= disco.TokenEndpoint,
                        ClientId= "sample_client",
                        ClientSecret= "sample_client_secret"
                    }
                );

            if(tokenResponse.IsError)
            {
                Console.WriteLine(tokenResponse.Error);
                return;
            }

            Console.WriteLine(tokenResponse.Json);


            var apiClient = new HttpClient();
            apiClient.SetBearerToken(tokenResponse.AccessToken);

            var response = await apiClient.PostAsync("http://localhost:5000/IdentityServer", null);
            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine(response.StatusCode);
            }
            else
            {
                var content = await response.Content.ReadAsStringAsync();
                Console.WriteLine(JArray.Parse(content));
            }


            Console.ReadKey();
        }
    }

專案執行效果如圖

 

 

學習連結地址:https://www.cnblogs.com/stulzq/p/7495129.html