IdentityServer4 中文文档 -9- (快速入门)使用客户端凭证保护API
IdentityServer4 中文文档 -9- (快速入门)使用客户端凭证保护API
原文:http://docs.identityserver.io/en/release/quickstarts/1_client_credentials.html
上一篇:IdentityServer4 中文文档 -8- (快速入门)设置和概览
下一篇:IdentityServer4 中文文档 -10- (快速入门)使用密码保护API
当前快速入门展示了使用 IdentityServer 保护 API 的最基础的场景。
在这个场景中,我们定义一个 API,同时定义一个 想要访问这个 API 的 客户端。客户端将从 IdentityServer 请求获得一个访问令牌,然后用这个令牌来获得 API 的访问权限。
定义 API
范围(Scopes)用来定义系统中你想要保护的资源,比如 API。
由于当前演练中我们使用的是内存配置 —— 添加一个 API,你需要做的只是创建一个 ApiResource 类型的实例,并为它设置合适的属性。
向你的项目中添加一份文件(比如:Config.cs),然后添加如下代码:
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1", "我的 API")
};
}
定义 客户端
下一步是定义能够访问上述 API 的客户端。
在该场景中,客户端不会有用户参与交互,并且将使用 IdentityServer 中所谓的客户端密码(Client Secret)来认证。添加如下代码到你的配置中:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
// 没有交互性用户,使用 clientid/secret 实现认证。
AllowedGrantTypes = GrantTypes.ClientCredentials,
// 用于认证的密码
ClientSecrets =
{
new Secret("secret".Sha256())
},
// 客户端有权访问的范围(Scopes)
AllowedScopes = { "api1" }
}
};
}
配置 IdentityServer
为了让 IdentityServer 使用你的 Scopes 和 客户端 定义,你需要向 ConfigureServices 方法中添加一些代码。你可以使用便捷的扩展方法来实现 —— 它们在幕后会添加相关的存储和数据到 DI 系统中:
public void ConfigureServices(IServiceCollection services)
{
// 使用内存存储,密钥,客户端和资源来配置身份服务器。
services.AddIdentityServer()
.AddTemporarySigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}
现在,如果你运行服务器并将浏览器导航到 http://localhost:5000/.well-known/openid-configuration,你应该看能到所谓的 发现文档。你的客户端和 API 将使用这些信息来下载所需要的配置数据。

添加 API
下一步,向你的解决方案中添加 API。
你可以使用 ASP.NET Core Web API 模板,或者添加 Microsoft.AspNetCore.Mvc 程序包到你的项目中。再一次建议你像之前一样,控制所使用的端口并使用与之前配置 Kestrel 和启动资料相同的技术。该演练假设你已经将你的 API 配置为运行于 http://localhost:5001 之上。
控制器
添加一个新的控制器到你的 API 项目中:
[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 });
}
}
这个控制器将在后面被用于测试授权需求,同时通过API的眼睛(浏览工具)来可视化身份信息。
配置
接下来,添加认证中间件到 API 宿主。该中间件的主要工作是:
- 验证输入的令牌以确保它来自可信任的发布者(IdentityServer);
- 验证令牌是否可用于该 api(也就是 Scope)。
将 IdentityServer4.AccessTokenValidation NuGet 程序包添加到你的 API 项目:

你还需要添加中间件到你的 HTTP 管道中 —— 必须在添加 MVC 之前添加,比如:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions()
{
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ApiName = "api1"
});
app.UseMvc();
}
如果你使用浏览器导航到上述控制器(http://localhost:5001/identity),你应该收到返回的 401 状态码。这意味着你的 API 要求提供证书。
这样一来, API 就是受 IdentityServer 保护的了。
创建客户端
最后一个步骤是编写一个客户端来请求访问令牌,然后使用这个令牌来访问 API。为此你需要为你的解决方案添加一个控制台应用程序。
IdentityServer 上的令牌端点实现了 OAuth 2.0 协议,你应该使用合法的 HTTP 来访问它。然而,我们有一个叫做 IdentityModel 的客户端库,它将协议交互封装到了一个易于使用的 API 里面。
添加 IdentityModel NuGet 程序包到你的客户端项目中。

IdentityModel 包含了一个用于 发现端点 的客户端库。这样一来你只需要知道 IdentityServer 的基础地址 —— 实际的端点地址可以从元数据中读取:
// 从元数据中发现端口
var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
接着你可以使用 TokenClient 类型来请求令牌。为了创建一个该类型的实例,你需要传入令牌端点地址、客户端id和密码。
然后你可以使用 RequestClientCredentialsAsync 方法来为你的目标 API 请求一个令牌:
// 请求以获得令牌
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);
注意:从控制台中复制和粘贴访问令牌到 jwt.io 以检查令牌的合法性。
最后是调用 API。
为了发送访问令牌到 API,你一般要使用 HTTP 授权 header。这可以通过 SetBearerToken 扩展方法来实现:
// 调用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));
}
最终输出看起来应该是这样的:

注意:默认情况下访问令牌将包含 scope 身份信息,生命周期(nbf 和 exp),客户端 ID(client_id) 和 发行者名称(iss)。
进一步实践
当前演练目前主要关注的是成功的步骤:
- 客户端可以请求令牌
- 客户端可以使用令牌来访问 API
你现在可以尝试引发一些错误来学习系统的相关行为,比如:
- 尝试在 IdentityServer 未运行时(unavailable)连接它
- 尝试使用一个非法的客户端id或密码来请求令牌
- 尝试在请求令牌的过程中请求一个非法的 scope
- 尝试在 API 未运行时(unavailable)调用它
- 不向 API 发送令牌
- 配置 API 为需要不同于令牌中的 scope
上一篇:IdentityServer4 中文文档 -8- (快速入门)设置和概览
下一篇:IdentityServer4 中文文档 -10- (快速入门)使用密码保护API
IdentityServer4 中文文档 -9- (快速入门)使用客户端凭证保护API的更多相关文章
- IdentityServer4 中文文档 -16- (快速入门)使用 EntityFramework Core 存储配置数据
IdentityServer4 中文文档 -16- (快速入门)使用 EntityFramework Core 存储配置数据 原文:http://docs.identityserver.io/en/r ...
- IdentityServer4 中文文档 -15- (快速入门)添加 JavaScript 客户端
IdentityServer4 中文文档 -15- (快速入门)添加 JavaScript 客户端 原文:http://docs.identityserver.io/en/release/quicks ...
- IdentityServer4 中文文档 -14- (快速入门)使用 ASP.NET Core Identity
IdentityServer4 中文文档 -14- (快速入门)使用 ASP.NET Core Identity 原文:http://docs.identityserver.io/en/release ...
- IdentityServer4 中文文档 -13- (快速入门)切换到混合流并添加 API 访问
IdentityServer4 中文文档 -13- (快速入门)切换到混合流并添加 API 访问 原文:http://docs.identityserver.io/en/release/quickst ...
- IdentityServer4 中文文档 -12- (快速入门)添加外部认证支持
IdentityServer4 中文文档 -12- (快速入门)添加外部认证支持 原文:http://docs.identityserver.io/en/release/quickstarts/4_e ...
- IdentityServer4 中文文档 -11- (快速入门)添加基于 OpenID Connect 的用户认证
IdentityServer4 中文文档 -11- (快速入门)添加基于 OpenID Connect 的用户认证 原文:http://docs.identityserver.io/en/releas ...
- IdentityServer4 中文文档 -8- (快速入门)设置和概览
IdentityServer4 中文文档 -8- (快速入门)设置和概览 原文:http://docs.identityserver.io/en/release/quickstarts/0_overv ...
- IdentityServer4 中文文档 -10- (快速入门)使用密码保护API
IdentityServer4 中文文档 -10- (快速入门)使用密码保护API 原文:http://docs.identityserver.io/en/release/quickstarts/2_ ...
- IdentityServer4 中文文档 -7- (简介)贡献
IdentityServer4 中文文档 -7- (简介)贡献 原文:http://docs.identityserver.io/en/release/intro/contributing.html ...
随机推荐
- python模块:time
# encoding: utf-8 # module time # from (built-in) # by generator 1.145 """ This modul ...
- ELK部署与使用总结
前言 自己最近在负责elk的工作,在这里想写一个总结,把好多遇到的问题啥的,都写一下,也做个笔记, 目录 环境介绍 kafka,zookeeper安装 logstash安装 elasticsearch ...
- mysql数据库的常用知识
问题一:如果使用可视化工具链接mysql? mysql默认情况下是不支持远程连接的!只需要几个步骤就能轻松搞定了. 1.vi /etc/mysql/my.cnf 修改里面bind-address项,将 ...
- 【算法】实现字典API:有序数组和无序链表
参考资料 <算法(java)> — — Robert Sedgewick, Kevin Wayne <数据结构> ...
- 关于java集合的一些操作
1.数组转集合 java提供了一个方法:Arrays.asList(T... a)的方法. 测试: String[] arr = {"Lida","huanda" ...
- 每日分享!canvas的使用~
今天大概的说下canvas的使用~ canvas是H5新增的一个元素,可以用来在canvas上绘制一些图形! 如何使用canvas呢? 首先我们用canvas绘制一条直线! <!DO ...
- Delphi - 子窗体继承父窗体后如何显示父窗体上的控件
1.创建子窗体Form1 File -> New -> Form,新建一个form,在form的单元文件中修改 2.子窗体中引用父窗体单元 uses TFatherForm 3.将子窗体中 ...
- 建立一个类似于天眼的Android应用程序:第4部分 - 持久收集联系人,通话记录和短信(SMS)
建立一个类似于天眼的Android应用程序:第4部分 - 持久收集联系人,通话记录和短信(SMS) 电话黑客android恶意软件编程黑客入侵linux 随着我们继续我们的系列,AMUNET应用程序变 ...
- APK防护——Anti_Virtual App的思路和实现
作者:HAI_i 原文来自:https://bbs.ichunqiu.com/thread-42982-1-1.html 0×00 前言 Virtual App是一个很强大的存在,破坏了Android ...
- Tools - 一些代码阅读的方法
1 初始能力 让阅读思路清晰连贯,保持在程序的流程架构和逻辑实现上,不被语法.编程技巧和业务流程等频繁地阻碍和打断. 语言基础:熟悉基础语法,常用的函数.库.编程技巧等: 了解设计模式.构建工具.代码 ...