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


一.前言

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

二.使用客戶端認證保護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文件:

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文件中:

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方法添加代碼。

Startup.cs

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的各種元數據信息。

首次啟動時,IdentityServer將為您創建一個開發人員簽名密鑰,它是一個名為tempkey.rsa的文件。 您不必將該文件檢入源代碼管理中,如果該文件不存在,將重新創建該文件。

七.添加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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM