Identity Server 4客戶端認證控制訪問API

項目源碼:

鏈接: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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章