IdentityServer4快速入门#1: 使用客户端凭据保护API

使用客户端凭据保护API
以下Identity Server 4快速入门提供了各种常见IdentityServer方案的分步说明。 这些从绝对的基础开始,并随着它们的发展而变得更加复杂。 我们建议您按顺序进行操作。

要查看完整列表,请转到IdentityServer4快速入门概述。

第一个快速入门是使用IdentityServer保护API的最基本方案。 在本快速入门中,您将定义一个API和一个用于访问它的客户端。 客户端将使用其客户端ID向Identity Server请求访问令牌,然后秘密将使用该令牌来访问API。

源码

通过所有这些快速入门,您可以在 IdentityServer4 仓库。 此快速入门的项目是 Quickstart #1: 使用客户端凭据保护API

Dotnet 模板

dotnet CLI的IdentityServer模板是快速入门的良好起点。 要安装模板,请打开控制台窗口,然后键入以下命令:

dotnet new -i IdentityServer4.Templates

它们将用作各种教程的起点。

设置ASP.NET Core应用程序

首先为应用程序创建目录-然后使用我们的模板创建包含基本IdentityServer设置的ASP.NET Core应用程序,例如:

cd quickstart

md src
cd src

dotnet new is4empty -n IdentityServer

这将创建以下文件:
IdentityServer.csproj-项目文件和Properties \ launchSettings.json文件
Program.cs和Startup.cs-主应用程序入口点
Config.cs-IdentityServer资源和客户端配置文件
现在,您可以使用自己喜欢的文本编辑器来编辑或查看文件。 如果要获得Visual Studio支持,可以添加如下解决方案文件:

cd ..
dotnet new sln -n Quickstart

并添加您的IdentityServer项目(请牢记此命令,因为我们将在下面创建其他项目):

dotnet sln add .\src\IdentityServer\IdentityServer.csproj

注意

在Kestrel上运行或在IISExpress上随机运行时,此模板中使用的协议为http,端口设置为5000。 您可以在Properties \ launchSettings.json文件中进行更改。 但是,所有快速入门说明都将假定您使用Kestrel上的默认端口以及http协议,这对于本地开发已经足够。 对于生产方案,应切换到https。

定义API资源

API是您系统中要保护的资源。 资源定义可以通过多种方式加载,您在上面用于创建项目的模板显示了如何使用“代码作为配置”方法。

Config.cs已经为您创建。 打开它,更新代码,如下所示:

public static class Config
{
    public static IEnumerable<ApiResource> Apis =>
        new List<ApiResource>
        {
            new ApiResource("api1", "My API")
        };
}

(查看完整文件 here).

注意

如果您将在生产环境中使用此功能,那么给您的API取一个逻辑名称就很重要。 开发人员将使用它通过身份服务器连接到您的api。 它应该以简单的方式向开发人员和用户描述您的api。

定义客户端

下一步是定义用于访问新API的客户端应用程序。

对于这种情况,客户端将没有交互式用户,并且将通过IdentityServer使用所谓的客户端密钥进行身份验证。

为此,添加一个客户端定义:

public static IEnumerable<Client> Clients =>
    new List<Client>
    {
        new Client
        {
            ClientId = "client",

            // 没有互动用户,请使用clientid / secret进行身份验证
            AllowedGrantTypes = GrantTypes.ClientCredentials,

            // 密钥认证方式
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },

            // 客户有权访问的范围
            AllowedScopes = { "api1" }
        }
    };

您可以将ClientId和ClientSecret视为应用程序本身的登录名和密码。 它将您的应用程序标识到身份服务器,以便它知道哪个应用程序正在尝试与其连接。

配置IdentityServer

加载资源和客户端定义发生在Startup.cs中-模板已经为您完成了此操作:

public void ConfigureServices(IServiceCollection services)
{
    var builder = services.AddIdentityServer()
        .AddInMemoryApiResources(Config.Apis)
        .AddInMemoryClients(Config.Clients);

    // 为了简洁起见,省略了
}

就是这样,您的身份服务器现在应该已配置。 如果运行服务器并在浏览器中导航到http://localhost:5000/.well-known/openid-configuration,则应该看到所谓的发现文档。 发现文档是身份服务器中的标准端点。 您的客户端和API将使用发现文档来下载必要的配置数据。

image.png

添加API

接下来,将API添加到您的解决方案中。

您可以使用Visual Studio中的ASP.NET Core Web API模板,也可以使用.NET CLI来创建API项目,如此处所述。 从src文件夹中运行以下命令:

dotnet new web -n Api

然后通过运行以下命令将其添加到解决方案中:

cd ..
dotnet sln add .\src\Api\Api.csproj

将API应用程序配置为仅在http://localhost:5001上运行。 您可以通过编辑Properties文件夹中的launchSettings.json文件来实现。 将应用程序URL设置更改为:

"applicationUrl": "http://localhost:5001"

Controller

添加一个名为IdentityController的新类:

[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的眼睛可视化声明身份。

添加Nuget依赖项

为了使配置步骤起作用,必须添加nuget软件包依赖项,请在根目录中运行此命令。
dotnet添加.\src\api\Api.csproj package Microsoft.AspNetCore.Authentication.JwtBearer

配置

最后一步是将身份验证服务添加到DI(依赖注入),并将身份验证中间件添加到管道。 这些将:

验证传入令牌以确保它来自受信任的发行者
验证令牌是否可以与此API一起使用(也称为受众群体)
更新启动看起来像这样:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        services.AddAuthentication("Bearer")
            .AddJwtBearer("Bearer", options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.Audience = "api1";
            });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}
  • AddAuthentication 将身份验证服务添加到DI并将Bearer配置为默认方案。
  • UseAuthentication 将身份验证中间件添加到管道中,以便在每次调用主机时将自动执行身份验证。
  • UseAuthorization 添加了授权中间件,以确保匿名客户端无法访问我们的API端点。

创建客户端

最后一步是编写一个请求访问令牌的客户端,然后使用该令牌访问API。 为此,将控制台项目添加到您的解决方案中,请记住在src中创建它:

dotnet new console -n Client

然后像以前一样,使用以下命令将其添加到您的解决方案中:

cd ..
dotnet sln add .\src\Client\Client.csproj

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

IdentityModel NuGet包添加到您的客户端。 这可以通过Visual Studio的Nuget程序包管理器或dotnet CLI来完成:

dotnet add package IdentityModel

IdentityModel包括一个与发现端点一起使用的客户端库。 这样,您只需要知道IdentityServer的基地址-可以从元数据中读取实际的端点地址:

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

接下来,您可以使用发现文档中的信息向IdentityServer请求令牌以访问api1

// request token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
    Address = disco.TokenEndpoint,

    ClientId = "client",
    ClientSecret = "secret",
    Scope = "api1"
});

if (tokenResponse.IsError)
{
    Console.WriteLine(tokenResponse.Error);
    return;
}

Console.WriteLine(tokenResponse.Json);

查看完整文件 这里

注意

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

调用API

要将访问令牌发送到API,通常使用HTTP授权标头。 这是使用SetBearerToken扩展方法完成的:

// call api
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);

var response = await apiClient.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
    Console.WriteLine(response.StatusCode);
}
else
{
    var content = await response.Content.ReadAsStringAsync();
    Console.WriteLine(JArray.Parse(content));
}

控制台输出应该像下面这样:


image.png

进一步的实验

本演练重点介绍了迄今为止的成功之路

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

现在,您可以尝试挑出错误,以了解系统的行为,例如

  • 尝试在未运行时连接到IdentityServer(不可用)
  • 尝试使用无效的客户端ID或机密请求令牌
  • 尝试在令牌请求期间请求无效的范围
  • 尝试在未运行时调用API(不可用)
  • 不要将令牌发送到API
  • 配置API以要求与令牌中的作用域不同的作用域
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容