IdentityServer4(7)- 使用客戶端認證控制API訪問(客戶端受權模式)

一.前言

本文已更新到 .NET Core 2.2
本文包括後續的Demo都會放在github:https://github.com/stulzq/IdentityServer4.Samples (QuickStart的幾個Demo隨着本系列的更新,目前爲從官方Demo倉庫的拷貝,防止本文和Demo不匹配,由於官方Demo和文檔一直在更新,本系列更新速度可能會慢一步)。
這裏特別說明一下:快速入門以及Topic系列爲了保持到最新,目前幾乎都是翻譯的官方文檔(以往的不適合最新版本就換掉了),須要深刻一點的請看實戰系列。git

二.使用客戶端認證保護API

此示例介紹了使用IdentityServer保護API的最基本場景。github

在這種狀況下,咱們將定義一個API和要訪問它的客戶端。 客戶端將在IdentityServer上請求訪問令牌,並使用它來訪問API。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文件:app

public static class Config
    {
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new IdentityResource[]
            {
                new IdentityResources.OpenId()
            };
        }

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

        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的客戶端模式進行身份驗證。 將如下代碼添加到Config.cs文件中:asp.net

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以使用Scope和客戶端定義,您須要向ConfigureServices方法添加代碼。ide

Startup.cspost

public void ConfigureServices(IServiceCollection services)
{
    var builder = services.AddIdentityServer()
        .AddDeveloperSigningCredential()
        .AddInMemoryIdentityResources(Config.GetIdentityResources())
        .AddInMemoryApiResources(Config.GetApis())
        .AddInMemoryClients(Config.GetClients());

    // rest omitted
}

public void Configure(IApplicationBuilder app)
{
        if (Environment.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // uncomment if you want to support static files
        //app.UseStaticFiles();

        app.UseIdentityServer();

        // uncomment, if you wan to add an MVC-based UI
        //app.UseMvcWithDefaultRoute();
}

運行此項目,打開瀏覽器訪問http://localhost:5000/.well-known/openid-configuration你將會看到IdentityServer的各類元數據信息。ui

首次啓動時,IdentityServer將爲您建立一個開發人員簽名密鑰,它是一個名爲tempkey.rsa的文件。 您沒必要將該文件檢入源代碼管理中,若是該文件不存在,將從新建立該文件。.net

七.添加API

在項目Api中添加一個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 });
    }
}

最後一步是將身份驗證服務添加到DI和身份驗證中間件到管道。 這些將:

  • 驗證傳入令牌以確保它來自受信任的頒發者
  • 驗證令牌是否有效用於此API(也稱爲 audience)

將Startup更新爲以下所示:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvcCore()
            .AddAuthorization()
            .AddJsonFormatters();

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

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

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

        app.UseMvc();
    }
}

AddAuthentication 將身份認證服務添加到DI,並將「Bearer」配置爲默認方案。 AddJwtBearer 將 JWT 認證處理程序添加到DI中以供身份認證服務使用。 UseAuthentication 將身份認證中間件添加到管道中,所以將在每次調用API時自動執行身份驗證。

若是在瀏覽器訪問(http:// localhost:5001/identity),你會獲得HTTP 401的結果。 這意味着您的API須要憑據。

就是這樣,API如今受 IdentityServer 保護。

八.建立客戶端

爲 "Client" 項目添加 Nuget 包:IdentityModel

IdentityModel 包括用於發現 IdentityServer 各個終結點(EndPoint)的客戶端庫。這樣您只須要知道 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;
}

DiscoveryClient 已在最新版移除

接下來,您可使用從 IdentityServer 元數據獲取到的Token終結點請求令牌:

// 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);

九.調用API

要將Token發送到API,一般使用HTTP Authorization標頭。 這是使用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));
}

輸出應以下所示:

默認狀況下,Token將包含有關 Scope,生命週期(nbf和exp),客戶端ID(client_id)和頒發者名稱(iss)的身份信息單元(Claim)。

十.使用Postman調試

十一.項目所用代碼

github地址: https://github.com/stulzq/IdentityServer4.Samples/tree/master/Quickstarts/1_ClientCredentials

相關文章
相關標籤/搜索