根据模板创建项目

https://identityserver4.readthedocs.io/en/latest/quickstarts/0_overview.html

使用终端输入dotnet new -i IdentityServer4.Templates安装模板。
安装之后,有以下6个模板。
image.png
使用最后一个创建。

项目测试

修改Config

Config.cs中IdentityResources代表身份资源,ApiScopes主要用于为Client提供accesstoken中的scope声明的值。Client客户端。
Config.csClients客户端只保留 GrantTypes.ClientCredentials授权方式。

  1. // Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
  2. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
  3. using IdentityServer4;
  4. using IdentityServer4.Models;
  5. using System.Collections.Generic;
  6. namespace ids4
  7. {
  8. public static class Config
  9. {
  10. public static IEnumerable<IdentityResource> IdentityResources =>
  11. new IdentityResource[]
  12. {
  13. new IdentityResources.OpenId(),
  14. new IdentityResources.Profile(),
  15. };
  16. public static IEnumerable<ApiScope> ApiScopes =>
  17. new ApiScope[]
  18. {
  19. new ApiScope("scope1","myApi"),
  20. };
  21. public static IEnumerable<Client> Clients =>
  22. new Client[]
  23. {
  24. new Client
  25. {
  26. ClientId = "console client",
  27. ClientName = "Client Credentials Client",
  28. AllowedGrantTypes = GrantTypes.ClientCredentials,
  29. ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
  30. AllowedScopes =
  31. {
  32. "scope1",
  33. IdentityServerConstants.StandardScopes.OpenId
  34. }
  35. }
  36. };
  37. }
  38. }

新建项目ApiResourceWebApi项目

Startup.cs

  1. using Microsoft.AspNetCore.Builder;
  2. using Microsoft.AspNetCore.Hosting;
  3. using Microsoft.Extensions.DependencyInjection;
  4. using Microsoft.IdentityModel.Tokens;
  5. namespace ApiResourceWebApi
  6. {
  7. public class Startup
  8. {
  9. public void ConfigureServices(IServiceCollection services)
  10. {
  11. services.AddControllers();
  12. services.AddAuthentication("Bearer")
  13. .AddJwtBearer("Bearer", options =>
  14. {
  15. options.Authority = "http://localhost:5000";
  16. options.RequireHttpsMetadata = false;
  17. options.TokenValidationParameters = new TokenValidationParameters
  18. {
  19. ValidateAudience = false
  20. };
  21. });
  22. }
  23. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  24. {
  25. app.UseRouting();
  26. app.UseAuthentication();
  27. app.UseAuthorization();
  28. app.UseEndpoints(endpoints => endpoints.MapControllers());
  29. }
  30. }
  31. }

新建Controllers文件夹。
新建IdentityController类。

  1. using Microsoft.AspNetCore.Authorization;
  2. using Microsoft.AspNetCore.Mvc;
  3. using System.Linq;
  4. namespace ApiResourceWebApi.Controllers
  5. {
  6. [Route("identity")]
  7. [Authorize]
  8. public class IdentityController : ControllerBase
  9. {
  10. [HttpGet]
  11. public IActionResult Get()
  12. {
  13. return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
  14. }
  15. }
  16. }

注意该项目启动端口要和IDS项目启动端口不一样。

新建Console客户端

安装IdentityModel Nuget包

  1. using IdentityModel.Client;
  2. using Newtonsoft.Json.Linq;
  3. using System;
  4. using System.Net.Http;
  5. using System.Threading.Tasks;
  6. namespace ConsoleClient
  7. {
  8. internal class Program
  9. {
  10. static async Task Main(string[] args)
  11. {
  12. // discovery
  13. var client = new HttpClient();
  14. var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000/");
  15. if (disco.IsError)
  16. {
  17. Console.WriteLine(disco.Error);
  18. return;
  19. }
  20. // request access token
  21. var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest()
  22. {
  23. Address = disco.TokenEndpoint,
  24. ClientId = "console client",
  25. ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",
  26. // openid 是获取用户信息的,而ClientCredentials不代表任何用户,获取openid显然不合理的
  27. Scope = "scope1"
  28. });
  29. if (tokenResponse.IsError)
  30. {
  31. Console.WriteLine(tokenResponse.Error);
  32. return;
  33. }
  34. // call Identity Resource API
  35. var apiClient = new HttpClient();
  36. apiClient.SetBearerToken(tokenResponse.AccessToken);
  37. var response = await apiClient.GetAsync("http://localhost:5002/identity");
  38. if (!response.IsSuccessStatusCode)
  39. {
  40. Console.WriteLine(response.StatusCode);
  41. }
  42. else
  43. {
  44. var content = await response.Content.ReadAsStringAsync();
  45. Console.WriteLine(JArray.Parse(content));
  46. }
  47. Console.ReadKey();
  48. }
  49. }
  50. }

image.png
这样记录意义不大。需详细的过程化记录。