IdentityServer4 实践- 使用客户端凭据保护API

1-创建公共类库 IDS4.Core

 

 

1.1-引用 IdentityServer4 

1.2-创建 Config.cs 配置类

 1 using IdentityServer4.Models;
 2 
 3 namespace IDS4.Core.ClientCredentials
 4 {
 5     /// <summary>
 6     /// 配置文件(使用客户端凭据)
 7     /// </summary>
 8     public static class Config
 9     {
10         private const string api_scope_one = "api1";
11 
12         public static IEnumerable<ApiScope> ApiScopes =>
13                                                new List<ApiScope>
14                                                {
15                                                     new ApiScope(api_scope_one, "第一个API")
16                                                };
17 
18         public static IEnumerable<Client> Clients =>
19                                                 new List<Client>
20                                                 {
21                                                     new Client
22                                                     {
23                                                         //可以将 ClientId 和 ClientSecret 视为应用程序本身的登录名和密码
24                                                         ClientId = "client",
25 
26                                                         // 没有交互式用户,使用 clientid/secret 进行身份验证
27                                                         AllowedGrantTypes = GrantTypes.ClientCredentials,
28 
29                                                         // 用于身份验证的密钥
30                                                         ClientSecrets =
31                                                         {
32                                                             new Secret("secret".Sha256())
33                                                         },
34 
35                                                         // 客户端有权访问的范围
36                                                         AllowedScopes = { api_scope_one }
37                                                     }
38                                                 };
39 
40     }
41 }
View Code

2-创建身份服务器( Identity Server)IDS4.Server

PS:使用站点空模板

 

 

2.1-引用IDS4.Core

 

2.2-配置ConfigService

1 builder.Services.AddIdentityServer()
2     // 这仅适用于没有证书可以使用的开发场景。
3     .AddDeveloperSigningCredential()
4     .AddInMemoryApiScopes(IDS4.Core.ClientCredentials.Config.ApiScopes)
5     .AddInMemoryClients(IDS4.Core.ClientCredentials.Config.Clients);
View Code

2.3-配置ConfigApp

1 var app = builder.Build();
2 app.UseIdentityServer();
View Code

Ps:完整的Program.cs

 1 var builder = WebApplication.CreateBuilder(args);
 2 
 3 builder.Services.AddIdentityServer()
 4     // 这仅适用于没有证书可以使用的开发场景。
 5     .AddDeveloperSigningCredential()
 6     .AddInMemoryApiScopes(IDS4.Core.ClientCredentials.Config.ApiScopes)
 7     .AddInMemoryClients(IDS4.Core.ClientCredentials.Config.Clients);
 8 
 9 
10 var app = builder.Build();
11 app.UseIdentityServer();
12 
13 app.MapGet("/", () => "Hello World!");
14 
15 app.Run();
View Code

2.4-端口 5010

http://localhost:5010

3-创建API站点 IDS4.API

PS:选 ASP.Net Core Web API 模板

 

 

 

3.1-引用 Microsoft.AspNetCore.Authentication.JwtBearer 类库

3.2-配置ConfigService

 1 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
 2     .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
 3     {
 4         //验证传入的令牌以确保它来自受信任的发行者
 5         options.Authority = "http://localhost:5010";
 6         // 禁用HTTPS
 7         options.RequireHttpsMetadata = false;
 8         options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
 9         {
10             //验证令牌是否有效与此 API 一起使用(又名 audience 受众)
11             ValidateAudience = false
12         };
13     });
View Code

3.3-配置ConfigApp

app.UseAuthentication();

Ps:完整的Program.cs

 1 using Microsoft.AspNetCore.Authentication.JwtBearer;
 2 
 3 var builder = WebApplication.CreateBuilder(args);
 4 
 5 // Add services to the container.
 6 
 7 builder.Services.AddControllers();
 8 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
 9     .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
10     {
11         //验证传入的令牌以确保它来自受信任的发行者
12         options.Authority = "http://localhost:5010";
13         // 禁用HTTPS
14         options.RequireHttpsMetadata = false;
15         options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
16         {
17             //验证令牌是否有效与此 API 一起使用(又名 audience 受众)
18             ValidateAudience = false
19         };
20     });
21 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
22 builder.Services.AddEndpointsApiExplorer();
23 builder.Services.AddSwaggerGen();
24 
25 var app = builder.Build();
26 
27 // Configure the HTTP request pipeline.
28 if (app.Environment.IsDevelopment())
29 {
30     app.UseSwagger();
31     app.UseSwaggerUI();
32 }
33 
34 app.UseAuthentication();
35 app.UseAuthorization();
36 
37 app.MapControllers();
38 
39 app.Run();
View Code

3.4-端口 5011

http://localhost:5011

 

3.5-添加 IdentityController 控制器

 1 using Microsoft.AspNetCore.Authorization;
 2 using Microsoft.AspNetCore.Mvc;
 3 
 4 // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
 5 
 6 namespace IDS4.API.Controllers
 7 {
 8     [Route("api/[controller]")]
 9     [ApiController]
10     [Authorize]
11     public class IdentityController : ControllerBase
12     {
13         [HttpGet]
14         public IActionResult Get()
15         {
16             return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
17         }
18     }
19 }
View Code

4-创建客户端 IDS4.Web

 

 

 

 

 

4.1-引用 IdentityModel 类库

 

 

4.2-从元数据中发现端点

 1  var client = new HttpClient();
 2             var disco = await client.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
 3             {
 4                 Address = "http://localhost:5010",
 5                 Policy = new DiscoveryPolicy { RequireHttps = false } //禁用Https
 6             });
 7 if(disco==null || disco.IsError)
 8 {
 9    Console.WriteLine(disco.Error);
10   return;
11 }
View Code

 

就是解析 http://localhost:5010/.well-known/openid-configuration 这个地址

 

 

4.3-请求令牌

 1 // 请求令牌
 2 var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
 3 {
 4     Address = disco.TokenEndpoint,
 5 
 6     ClientId = "client",
 7     ClientSecret = "secret",
 8     Scope = "api1"
 9 });
10 
11 if (tokenResponse.IsError)
12 {
13     Console.WriteLine(tokenResponse.Error);
14     return;
15 }
16 
17 Console.WriteLine(tokenResponse.Json);
View Code

 

4.4-调用API

 1 // 调用api
 2 var apiClient = new HttpClient();
 3 apiClient.SetBearerToken(tokenResponse.AccessToken);
 4 
 5 var response = await apiClient.GetAsync("https://localhost:6001/identity");
 6 if (!response.IsSuccessStatusCode)
 7 {
 8     Console.WriteLine(response.StatusCode);
 9 }
10 else
11 {
12     var content = await response.Content.ReadAsStringAsync();
13     Console.WriteLine(JArray.Parse(content));
14 }
View Code

 

Ps:完整的Index.cshtml.cs 的get 方法

 1 public async Task OnGet()
 2         {
 3             var client = new HttpClient();
 4             var disco = await client.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
 5             {
 6                 Address = "http://localhost:5010",
 7                 Policy = new DiscoveryPolicy { RequireHttps = false } //禁用Https
 8             });
 9             if (disco != null)
10             {
11                 if (disco.IsError)
12                     ViewData["data"] = disco.Error;
13                 else
14                 {
15                     var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
16                     {
17                         Address = disco.TokenEndpoint,
18                         ClientId = "client",
19                         ClientSecret = "secret",
20                         Scope = "api1"
21                     });
22                     if (tokenResponse != null)
23                     {
24                         if (tokenResponse.IsError)
25                             ViewData["data"] = tokenResponse.Json;
26                         else
27                         {
28                             var apiClient = new HttpClient();
29                             apiClient.SetBearerToken(tokenResponse.AccessToken);
30 
31                             var response = await apiClient.GetAsync("http://localhost:5011/api/identity");
32                             if (!response.IsSuccessStatusCode)
33                             {
34                                 Console.WriteLine(response.StatusCode);
35                                 ViewData["data"] = response.StatusCode;
36                             }
37                             else
38                             {
39                                 var content = await response.Content.ReadAsStringAsync();
40                                 ViewData["data"] = content;
41                                 Console.WriteLine(JArray.Parse(content));
42                             }
43                         }
44                     }
45                     else
46                     {
47                         ViewData["data"] = "访问失败";
48                     }
49                 }
50             }
51             else
52             {
53                 ViewData["data"] = "访问失败";
54             }
55         }
View Code

4.5-Index.cshtml

PS:鉴权时序图

 

 

 

posted @ 2022-01-05 15:20  细品人生  阅读(107)  评论(0编辑  收藏  举报