1-创建公共类库 IDS4.Core
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLxcTN2IzNwcjNtcjMxgDMzETNxUDMxAjMyAjMtMDO5IzMz8CXxAjMyAjMvw1M4kjMzMzLcd2bsJ2Lc12bj5ycn9Gbi52YuAjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
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);
2.3-配置ConfigApp
1 var app = builder.Build();
2 app.UseIdentityServer();
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();
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 });
3.3-配置ConfigApp
app.UseAuthentication();
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();
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 }
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 }
就是解析 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);
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 }
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 }
4.5-Index.cshtml
PS:鉴权时序图
漫漫人生,唯有激流勇进,不畏艰险,奋力拼搏,方能中流击水,抵达光明的彼岸