使用客户端凭据保护 API

quickstart 介绍了使用 IdentityServer 保护 API 的最基本场景。

接下来的场景,我们将定义一个 API 和一个想要访问它的客户端。 客户端将在 IdentityServer 上请求访问令牌并使用它来访问 API。

定义 API

在系统中定义您需要保护的资源的范围,比如 APIs。

由于我们演示的项目使用的是内存存储 - 您需要添加一个 API,它创建了一个类型为 ApiResource 的对象并设置了一些属性。

在您的项目中添加一个文件 (比如 Config.cs) ,然后把下面的代码放进去:

public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API")
};
}

定义客户端(client)

接下来就是定义一个用于访问这个 API 的客户端。

当前场景下,客户端是不需要用户操作的,并且 IdentityServer 校验客户端密钥。 将下面的代码添加到 Config.cs 文件中:

public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client", // no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials, // secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
}, // scopes that client has access to
AllowedScopes = { "api1" }
}
};
}

配置 IdentityServer

配置 IdentityServer 使您定义的范围(scopes)和客户端(client)生效,您需要把一下代码添加到 ConfigureServices 方法中。 您可以像下面一样,使用一些扩展方法,就能很方便的将相应的存储方式和数据注册到 DI 系统中

public void ConfigureServices(IServiceCollection services)
{
// configure identity server with in-memory stores, keys, clients and resources
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}

就是这样 - 当您运行服务器并在浏览器中输入 http://localhost:5000/.well-known/openid-configuration,您可以看到所谓(so-called)的发现文档。 您的客户端和 API 将用它来下载一些必要的配置数据。

添加 API

下面,添加一个 API 到你的解决方案。

您可以使用 ASP.NET Core Web API 模板。 同样,我们建议您使用与之前相同的方法来配置 Kestrel 和启动配置文件。 本演示项目假定您已将您的 API 配置为 http://localhost:5001

controller

在 API 中新建一个新的 controller:

[Route("identity")]
[Authorize]
public class IdentityController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
}

该 controller 将用于请求授权测试,并通过 API 视角来显示声明标识(claims identity)。

配置

最后一步是将认证服务添加到 DI 并把认证中间件(middleware)添加到管道中(pipeline)。这将会:

  • 验证传入的令牌以确保它来自受信任的颁发者
  • 验证该令牌是否可以访问该 API(又名作用域)

添加 IdentityServer4.AccessTokenValidation NuGet 包到你的项目中。

像下面这样更新你的 Startup

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters(); services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false; options.ApiName = "api1";
});
} public void Configure(IApplicationBuilder app)
{
app.UseAuthentication(); app.UseMvc();
}
}

AddAuthentication 将认证服务注册到 DI 并把 "Bearer" 配置为默认方案。 AddIdentityServerAuthentication 将 IdentityServer 访问令牌验证处理程序注册到 DI 以供认证服务使用。 UseAuthentication 把认证中间件(middleware)添加到管道,因此每次访问主机(host)都会自动执行认证。

如果您使用浏览器导航到 Identity 控制器 (http://localhost:5001/identity),返回的则应该是 401 状态码。这意味着您需要一个凭据才能访问这个 API 。

像这样,这个 API 就受到了 IdentityServer 的保护。

创建客户端(client)

最后一步,就是写一个客户端,用来请求访问令牌人,然后使用这个令牌去访问 API。因此,在您的解决方案中添加一个控制台程序 (完整代码请查看  这里)。

IdentityServer 中的令牌节点实现了 OAuth 2.0 协议,您可以使用原始的 HTTP 来访问它。但是,我们有一个名为 IdentityModel 的客户端使用库,它将协议交互封装在易于使用的 API 中。

在您的项目中添加 IdentityModel NuGet 包。

IdentityModel 包含一个发现节点(discovery endpoint)的客户端使用库。 这样您只需要知道 IdentityServer 的基地址(base-address) - 实际节点地址可以从元数据中获取

// discover endpoints from metadata
var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}

接下来,您可以使用 TokenClient 类来请求令牌。创建实例您只需要传递一个令牌节点地址,客户端 ID 和 密钥。

然后您可以使用 RequestClientCredentialsAsync 方法为您的 API 请求一个令牌

// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "client", "secret");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1"); if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
} Console.WriteLine(tokenResponse.Json);

Note

将访问令牌从控制台复制和粘贴到 jwt.io 以检查原始令牌。

最后一步就是调用 API。

将访问令牌发送到 API,您通常使用 HTTP 授权标头。 在这里使用 SetBearerToken 扩展方法来完成

// call api
var client = new HttpClient();
client.SetBearerToken(tokenResponse.AccessToken); var response = await client.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}

输出看起来应该像这样:

Note

默认情况下,访问令牌的声明将包含访问边界(scope),生命周期(lifetime (nbf and exp)),客户端 ID (client_id) 和发行者名称(issuer name (iss))。

进一步实验

到目前为止,该演示项目主要聚焦于

  • 客户端可以成功的请求令牌
  • 客户端能使用令牌访问 API

您现在可以尝试引发错误以便了解系统的运行方式,例如

  • 在 IdentityServer 没有运行的情况下,尝试连接它 (不可用)
  • 尝试使用无效的客户端ID或密钥来请求令牌
  • 尝试使用有效令牌访问该令牌可访问边界外的资源
  • 尝试在 API 没有运行的情况下,调用它 (不可用)
  • 不发送令牌到 API
  • 将 API 配置到令牌可访问边界外的资源范围中去

原文地址:https://github.com/ganqiyin/IdentityServer4/blob/dev/docs_cn/quickstarts/1_client_credentials.rst

【IdentityServer4文档】- 使用客户端凭据保护 API的更多相关文章

  1. asp.net core系列 54 IS4用客户端凭据保护API

    一. 概述 本篇开始进入IS4实战学习,从第一个示例开始,该示例是 “使用客户端凭据保护API”,这是使用IdentityServer保护api的最基本场景.该示例涉及到三个项目包括:Identity ...

  2. 第9章 使用客户端凭据保护API - Identity Server 4 中文文档(v1.0.0)

    快速入门介绍了使用IdentityServer保护API的最基本方案. 我们将定义一个API和一个想要访问它的客户端. 客户端将通过提供ClientCredentials在IdentityServer ...

  3. IdentityServer4 中文文档 -9- (快速入门)使用客户端凭证保护API

    IdentityServer4 中文文档 -9- (快速入门)使用客户端凭证保护API 原文:http://docs.identityserver.io/en/release/quickstarts/ ...

  4. .NET Core 3.0 使用Nswag生成Api文档和客户端代码

    摘要 在前后端分离.Restful API盛行的年代,完美的接口文档,成了交流的纽带.在项目中引入Swagger (也称为OpenAPI),是种不错的选择,它可以让接口数据可视化.下文将会演示 利用N ...

  5. 软件工程第4次作业------石墨文档Android客户端案例分析

    作业要求的博客链接:https://edu.cnblogs.com/campus/nenu/2016CS/homework/2505 分析产品:石墨文档Android客户端 第一部分 调研和评测 1. ...

  6. 使用 Swagger 文档化和定义 RESTful API

    大部分 Web 应用程序都支持 RESTful API,但不同于 SOAP API——REST API 依赖于 HTTP 方法,缺少与 Web 服务描述语言(Web Services Descript ...

  7. Atitit.论垃圾文件的识别与清理 文档类型垃圾文件 与api概要设计pa6.doc

    Atitit.论垃圾文件的识别与清理 文档类型垃圾文件 与api概要设计pa6.doc 1. 俩个问题::识别垃圾文件与清理策略1 1.1. 文件类型:pic,doc,v,m cc,isho pose ...

  8. Elasticsearch 7.x 之文档、索引和 REST API 【基础入门篇】

    前几天写过一篇<Elasticsearch 7.x 最详细安装及配置>,今天继续最新版基础入门内容.这一篇简单总结了 Elasticsearch 7.x 之文档.索引和 REST API. ...

  9. 【IdentityServer4文档】- 术语&演示服务器和测试

    术语 你需要了解一下,规范.文档和对象模型使用的术语有哪些. IdentityServer IdentityServer 是一个 OpenID Connect 提供程序 - 它实现了 OpenID C ...

随机推荐

  1. Spring Bean d的作用域

    在spring中,可以在<bean>元素的scop属性里设置bean的作用域,以决定这个bean是单实例的还是多实例的. 默认情况下,spring只为每个在IOC容器里声明的bean创建唯 ...

  2. windows下开启 PHP扩展Redis

    Redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set ...

  3. iPhone Plus手机的分辨率到底是多少,是1080×1920还是1242×2208?

    近日在准备AppStore上架的时候,需要提供屏幕快照,苹果官方的要求是: 5.5寸的iOS设备的分辨率是:是1080×1920:然而我们如果找一张Plus的屏幕截图,会发现截图的分辨率是1242×2 ...

  4. 快速认识LinkIt 7697开发板

    LinkIt 7697是一款多功能且价格亲民的开发板,可用来连接网络或你的各项装置,同时提供Wi-Fi及蓝芽两种联机功能.此开发板采用MediaTek MT7697芯片,比起其他类似的Wi-Fi/蓝芽 ...

  5. 文件句柄W模式

    f1=open('lo',encoding='utf-8',mode='w')f1.write('w4567')print(f1.tell())f1.close() #tell 告诉指针的位置(按字节 ...

  6. DotNetty学习笔记

    DotNetty项目本身的示例很容易运行起来,但是具体到真实的应用场景,还是需要进一步理解DotNetty的通道处理细节,这样才能够在实际项目应用中处理具体的问题. 简单的场景下会有以下几个问题,第一 ...

  7. 20155230 2016-2017-2 《Java程序设计》第四周学习总结

    20155230 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 1.使用extends进行扩充继承时private也会被继承但是子类不能在其中直接存取. 2 ...

  8. hasOwnProperty()函数

    hasOwnProperty()函数的返回值为Boolean类型.如果对象object具有名称为propertyName的属性,则返回true,否则返回false 例子: function Site( ...

  9. C#基础之接口

    对于接口一直以来都清楚自己理解的不深入,这两天重温以前的代码时更加发现对接口的理解仅仅限于定义而已,得好好学学接口了. 1.接口的特点 接口的定义是指定一组函数成员而不实现成员的引用类型,其它类型和接 ...

  10. php 批量载入文件的几种方式

    方式1:spl_autoload_register // Register the autoloader. /** * Contains the functionality for auto-load ...