IdentityServer4 使用客户端认证控制API访问(客户端授权模式)

  • A+
所属分类:IdentityServer4

IdentityServer4  使用客户端认证控制API访问(客户端授权模式)

使用客户端认证保护API

  • 此示例介绍了使用IdentityServer保护API的最基本场景。
  • 在这种情况下,我们将定义一个API和要访问它的客户端。 客户端将在IdentityServer上请求访问令牌,并使用它来访问API。
  • 准备

  • 创建一个名为QuickstartIdentityServer的ASP.NET Core Web 空项目(asp.net core 2.2),端口5000
  • 创建一个名为Api的ASP.NET Core Web Api 项目(asp.net core 2.2),端口5001
  • 创建一个名为Client的控制台项目(.net core 2.2)
  • 定义API、Identity资源

    在QuickstartIdentityServer项目中添加一个Config.cs文件:

    1. public static class Config  
    2.     {  
    3.         public static IEnumerable<IdentityResource> GetIdentityResources()  
    4.         {  
    5.             return new IdentityResource[]  
    6.             {  
    7.                 new IdentityResources.OpenId()  
    8.             };  
    9.         }  
    10.   
    11.         public static IEnumerable<ApiResource> GetApis()  
    12.         {  
    13.             return new List<ApiResource>  
    14.             {  
    15.                 new ApiResource("api1""My API")  
    16.             };  
    17.         }  
    18.   
    19.         public static IEnumerable<Client> GetClients()  
    20.         {  
    21.             return new List<Client>  
    22.             {  
    23.                 new Client  
    24.                 {  
    25.                     ClientId = "client",  
    26.   
    27.                     // no interactive user, use the clientid/secret for authentication  
    28.                     AllowedGrantTypes = GrantTypes.ClientCredentials,  
    29.   
    30.                     // secret for authentication  
    31.                     ClientSecrets =  
    32.                     {  
    33.                         new Secret("secret".Sha256())  
    34.                     },  
    35.   
    36.                     // scopes that client has access to  
    37.                     AllowedScopes = { "api1" }  
    38.                 }  
    39.             };  
    40.         }  
    41.     }  

    定义客户端

    对于这种情况,客户端将不具有交互式(人机交互)用户,并将使用IdentityServer的客户端模式进行身份验证。 将以下代码添加到Config.cs文件中:

    1. public static IEnumerable<Client> GetClients()  
    2. {  
    3.     return new List<Client>  
    4.     {  
    5.         new Client  
    6.         {  
    7.             ClientId = "client",  
    8.   
    9.             // no interactive user, use the clientid/secret for authentication  
    10.             AllowedGrantTypes = GrantTypes.ClientCredentials,  
    11.   
    12.             // secret for authentication  
    13.             ClientSecrets =  
    14.             {  
    15.                 new Secret("secret".Sha256())  
    16.             },  
    17.   
    18.             // scopes that client has access to  
    19.             AllowedScopes = { "api1" }  
    20.         }  
    21.     };  
    22. }  

    配置 IdentityServer

    要配置IdentityServer以使用Scope和客户端定义,您需要向ConfigureServices方法添加代码。Startup.cs

    1. public void ConfigureServices(IServiceCollection services)  
    2. {  
    3.     var builder = services.AddIdentityServer()  
    4.         .AddDeveloperSigningCredential()  
    5.         .AddInMemoryIdentityResources(Config.GetIdentityResources())  
    6.         .AddInMemoryApiResources(Config.GetApis())  
    7.         .AddInMemoryClients(Config.GetClients());  
    8.   
    9.     // rest omitted  
    10. }  
    11.   
    12. public void Configure(IApplicationBuilder app)  
    13. {  
    14.         if (Environment.IsDevelopment())  
    15.         {  
    16.             app.UseDeveloperExceptionPage();  
    17.         }  
    18.   
    19.         // uncomment if you want to support static files  
    20.         //app.UseStaticFiles();  
    21.   
    22.         app.UseIdentityServer();  
    23.   
    24.         // uncomment, if you wan to add an MVC-based UI  
    25.         //app.UseMvcWithDefaultRoute();  
    26. }  
  • 运行此项目,打开浏览器访问http://localhost:5000/.well-known/openid-configuration你将会看到IdentityServer的各种元数据信息。
  • 首次启动时,IdentityServer将为您创建一个开发人员签名密钥,它是一个名为tempkey.rsa的文件。 您不必将该文件检入源代码管理中,如果该文件不存在,将重新创建该文件。
  • 添加API

    在项目Api中添加一个Controller:IdentityController

    1. [Route("identity")]  
    2. [Authorize]  
    3. public class IdentityController : ControllerBase  
    4. {  
    5.     [HttpGet]  
    6.     public IActionResult Get()  
    7.     {  
    8.         return new JsonResult(from c in User.Claims select new { c.Type, c.Value });  
    9.     }  
    10. }  

    最后一步是将身份验证服务添加到DI和身份验证中间件到管道。 这些将:

  • 验证传入令牌以确保它来自受信任的颁发者
  • 验证令牌是否有效用于此API(也称为 audience)
  • 将Startup更新为如下所示:

    1. public class Startup  
    2. {  
    3.     public void ConfigureServices(IServiceCollection services)  
    4.     {  
    5.         services.AddMvcCore()  
    6.             .AddAuthorization()  
    7.             .AddJsonFormatters();  
    8.   
    9.         services.AddAuthentication("Bearer")  
    10.             .AddJwtBearer("Bearer", options =>  
    11.             {  
    12.                 options.Authority = "http://localhost:5000";  
    13.                 options.RequireHttpsMetadata = false;  
    14.   
    15.                 options.Audience = "api1";  
    16.             });  
    17.     }  
    18.   
    19.     public void Configure(IApplicationBuilder app)  
    20.     {  
    21.         app.UseAuthentication();  
    22.   
    23.         app.UseMvc();  
    24.     }  
    25. }  
  • AddAuthentication 将身份认证服务添加到DI,并将“Bearer”配置为默认方案。 AddJwtBearer 将 JWT 认证处理程序添加到DI中以供身份认证服务使用。
  • UseAuthentication 将身份认证中间件添加到管道中,因此将在每次调用API时自动执行身份验证。
  • 如果在浏览器访问(http:// localhost:5001/identity),你会得到HTTP 401的结果。 这意味着您的API需要凭据。
  • 就是这样,API现在受 IdentityServer 保护。
  • 创建客户端

  • 为 "Client" 项目添加 Nuget 包:IdentityModel
  • IdentityModel 包括用于发现 IdentityServer 各个终结点(EndPoint)的客户端库。这样您只需要知道 IdentityServer 的地址 - 可以从元数据中读取实际的各个终结点地址:

    1. // discover endpoints from metadata  
    2. var client = new HttpClient();  
    3. var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");  
    4. if (disco.IsError)  
    5. {  
    6.     Console.WriteLine(disco.Error);  
    7.     return;  
    8. }  

    接下来,您可以使用从 IdentityServer 元数据获取到的Token终结点请求令牌:

    1. // request token  
    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);  

    调用API

    要将Token发送到API,通常使用HTTP Authorization标头。 这是使用SetBearerToken扩展方法完成的:

    1. // call api  
    2. var client = new HttpClient();  
    3. client.SetBearerToken(tokenResponse.AccessToken);  
    4.   
    5. var response = await client.GetAsync("http://localhost:5001/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. }  

    IdentityServer4  使用客户端认证控制API访问(客户端授权模式)

    使用Postman调试

    IdentityServer4  使用客户端认证控制API访问(客户端授权模式)

    官方仓库对应代码

    https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Quickstarts/1_ClientCredentials

    钰玺

    发表评论

    :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: