• IdentityServer4 快速上手


    IdentityServer4 是一个基于 .NET Core 的 OpenID Connect 实现框架。

    基于框架创建可运行的应用,通常还需要多个步骤,添加引用、配置项目、框架初始化、按照一系列步骤启动应用等等。那么,基于 IdentityServer4 创建一个可运行的 OpenID Connect 服务器需要多少行代码呢?

    得益于 .net core 提供的项目模版支持,实际上,不需要你写一行代码,只需要执行几个简单的命令就可以了。

    1. 准备 IdentityServer4 模版

    还记得使用 .net core 的命令行工具 dotnet 创建项目使用的 new 命令吗?如果你希望创建名为 HelloWorld 的项目,那么,创建它的命令如下:

    dotnet new console -n HelloWorld

    该命令会在当前目录下创建 HelloWorld 子目录。命令执行完成之后,进入这个 HelloWorld 目录中,就可以通过 run 命令来运行了。

    >cd HelloWorld
    >dotnet run
    Hello World!

    这个 console 就是通过内置的模版来实现的。当前支持的模版可以通过 list 子命令列出

    dotnet new -list

    在 dotnet 中,还可以通过 -i 参数来安装新的模版。模版既可以通过一个路径提供,也可以通过一个 nuget_id 来提供。你可能已经想到了,IdentityServer4 就已经提供了一个预定义在 NuGet 中的模版:IdentityServer4.Templates,你可以直接在 NuGet 中找到它:https://www.nuget.org/packages/IdentityServer4.Templates。需要说明的是,同一个项目模版可能存在多个版本,在安装的时候,可以通过在模版名称后面使用两个冒号来分隔特定的版本号,默认情况下,只安装最新的稳定版本。

    所以,事情变得简单了。我们需要的就是先在本地安装这个模版,然后,使用这个模版就可以直接创建出完整的 IdentityServer4 项目,然后直接运行。

    dotnet new --install IdentityServer4.Templates

    NuGet 中的提示是安装特定的版本,现在的最新稳定版本是 3.1.1,所以命令变成了

    dotnet new --install IdentityServer4.Templates::3.1.1

    在命令的输出中,可以看到已经安装了多个关于 IdentityServer4 的模版

    TemplatesShort NameLanguageTags
    IdentityServer4 with AdminUI is4admin [C#] Web/IdentityServer4
    IdentityServer4 with ASP.NET Core Identity is4aspid [C#] Web/IdentityServer4
    IdentityServer4 Empty is4empty [C#] Web/IdentityServer4
    IdentityServer4 with Entity Framework Stores is4ef [C#] Web/IdentityServer4
    IdentityServer4 with In-Memory Stores and Test Users is4inmem [C#] Web/IdentityServer4
    IdentityServer4 Quickstart UI (UI assets only) is4ui [C#] Web/IdentityServer4

    这里面最为简单的项目模版就是 IdentityServer4 Empty 了,它简称为 is4empty ,我们下面就使用它来创建项目。

    2. 创建第一个 IdentityServer4 项目

    直接使用 .net core 的 new 命令来创建项目,我们将创建的项目命名为 IdentityServer

    dotnet new is4empty -n IdentityServer

    执行之后,会在当前目录下创建 IdentityServer 文件夹,所有的项目文件都位于其中。

    3. 启动应用

    使用 .net core 的 run 命令来启动项目,可以看到如下输出:

    dotnet new is4empty -n IdentityServer
    PS C:	empis4IdentityServer> dotnet run
    [19:34:49 Information]
    Starting host...
    ​
    [19:34:50 Information] IdentityServer4.Startup
    Starting IdentityServer4 version 3.1.0.0
    ​
    [19:34:50 Information] IdentityServer4.Startup
    You are using the in-memory version of the persisted grant store. This will store consent decisions, authorization codes, refrtion.
    ​
    [19:34:50 Information] IdentityServer4.Startup
    Using the default authentication scheme idsrv for IdentityServer
    ​
    [19:34:50 Debug] IdentityServer4.Startup
    Using idsrv as default ASP.NET Core scheme for authentication
    ​
    [19:34:50 Debug] IdentityServer4.Startup
    Using idsrv as default ASP.NET Core scheme for sign-in
    ​
    [19:34:50 Debug] IdentityServer4.Startup
    Using idsrv as default ASP.NET Core scheme for sign-out
    ​
    [19:34:50 Debug] IdentityServer4.Startup
    Using idsrv as default ASP.NET Core scheme for challenge
    ​
    [19:34:50 Debug] IdentityServer4.Startup
    Using idsrv as default ASP.NET Core scheme for forbid

    祝贺你!你已经成功创建了第一个可运行的 IdentityServer4 服务器!

    4. 访问配置信息

    虽然还没有写一行代码,但是,服务器已经在工作了,我们可以通过它的 .well-known 端点来访问服务器的配置信息,在浏览器的地址栏中,输入地址:http://localhost:5000/.well-known/openid-configuration,并回车。应该可以看到如下的响应信息。 

    {
        "issuer": "http://localhost:5000",
        "jwks_uri": "http://localhost:5000/.well-known/openid-configuration/jwks",
        "authorization_endpoint": "http://localhost:5000/connect/authorize",
        "token_endpoint": "http://localhost:5000/connect/token",
        "userinfo_endpoint": "http://localhost:5000/connect/userinfo",
        "end_session_endpoint": "http://localhost:5000/connect/endsession",
        "check_session_iframe": "http://localhost:5000/connect/checksession",
        "revocation_endpoint": "http://localhost:5000/connect/revocation",
        "introspection_endpoint": "http://localhost:5000/connect/introspect",
        "device_authorization_endpoint": "http://localhost:5000/connect/deviceauthorization",
        "frontchannel_logout_supported": true,
        "frontchannel_logout_session_supported": true,
        "backchannel_logout_supported": true,
        "backchannel_logout_session_supported": true,
        "scopes_supported": [
            "openid",
            "offline_access"
        ],
        "claims_supported": [
            "sub"
        ],
        "grant_types_supported": [
            "authorization_code",
            "client_credentials",
            "refresh_token",
            "implicit",
            "urn:ietf:params:oauth:grant-type:device_code"
        ],
        "response_types_supported": [
            "code",
            "token",
            "id_token",
            "id_token token",
            "code id_token",
            "code token",
            "code id_token token"
        ],
        "response_modes_supported": [
            "form_post",
            "query",
            "fragment"
        ],
        "token_endpoint_auth_methods_supported": [
            "client_secret_basic",
            "client_secret_post"
        ],
        "id_token_signing_alg_values_supported": [
            "RS256"
        ],
        "subject_types_supported": [
            "public"
        ],
        "code_challenge_methods_supported": [
            "plain",
            "S256"
        ],
        "request_parameter_supported": true
    }

     5. 查看项目代码

    5.1 项目文件

    项目文件名称为 IdentityServer4.csproj,内容如下:

    <Project Sdk="Microsoft.NET.Sdk.Web">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.1</TargetFramework>
      </PropertyGroup>
      
      <ItemGroup>
        <PackageReference Include="IdentityServer4" Version="3.1.0" />
        <PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
        <!-- <PackageReference Include="System.Security.Principal.Windows" Version="4.7.0" /> -->
      </ItemGroup>
    </Project>

    主要做了 3 件事:

    • 配置了项目为 Web 应用项目,通过 Sdk 属性指定了 Microsoft.NET.Sdk.Web,目标框架为 .net core 3.1。

    • 添加了对 IdentityServer4 的引用,这就是 IdentityServer4 的实现库

    • 添加了日志库 Serilog.AspNetCore

    5.2 Program.cs

    这里面相当多的代码是关于 Serilog 日志的配置,关于 Web 站点,只是使用了标准的 Startup 方式启动。

    // Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
    // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
    ​
    ​
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Hosting;
    using Serilog;
    using Serilog.Events;
    using Serilog.Sinks.SystemConsole.Themes;
    using System;
    ​
    namespace IdentityServer
    {
        public class Program
        {
            public static int Main(string[] args)
            {
                Log.Logger = new LoggerConfiguration()
                    .MinimumLevel.Debug()
                    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                    .MinimumLevel.Override("System", LogEventLevel.Warning)
                    .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
                    .Enrich.FromLogContext()
                    .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate)
                    .CreateLogger();
    ​
                try
                {
                    Log.Information("Starting host...");
                    CreateHostBuilder(args).Build().Run();
                    return 0;
                }
                catch (Exception ex)
                {
                    Log.Fatal(ex, "Host terminated unexpectedly.");
                    return 1;
                }
                finally
                {
                    Log.CloseAndFlush();
                }
            }
    ​
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                        webBuilder.UseSerilog();
                    });
        }
    }

    5.3 Startup.cs

    在 ConfigureServices() 中,最为关键的一行就是添加了 IdentityServer4 服务的支持。

    由于这是用于演示的空项目,所以,具体的 OpenID Connect 配置信息来自于一个代码文件 Config,并使用硬编码的方式来用于 IdentityServer

    var builder = services.AddIdentityServer()
      .AddInMemoryIdentityResources(Config.Ids)
      .AddInMemoryApiResources(Config.Apis)
      .AddInMemoryClients(Config.Clients);

    这个 Config.cs 文件中,还没有对这些信息进行配置。

    // Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
    // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
    ​
    ​
    using IdentityServer4.Models;
    using System.Collections.Generic;
    ​
    namespace IdentityServer
    {
        public static class Config
        {
            public static IEnumerable<IdentityResource> Ids =>
                new IdentityResource[]
                { 
                    new IdentityResources.OpenId()
                };
    ​
            public static IEnumerable<ApiResource> Apis =>
                new ApiResource[] 
                { };
            
            public static IEnumerable<Client> Clients =>
                new Client[] 
                { };
            
        }
    }

    在 Configure() 中,则启用了 IdentityServer 服务。

    app.UseIdentityServer();

    完整的代码如下所示:

    // Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
    // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
    ​
    ​
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    ​
    namespace IdentityServer
    {
        public class Startup
        {
            public IWebHostEnvironment Environment { get; }
    ​
            public Startup(IWebHostEnvironment environment)
            {
                Environment = environment;
            }
    ​
            public void ConfigureServices(IServiceCollection services)
            {
                // uncomment, if you want to add an MVC-based UI
                //services.AddControllersWithViews();
    var builder = services.AddIdentityServer()
                    .AddInMemoryIdentityResources(Config.Ids)
                    .AddInMemoryApiResources(Config.Apis)
                    .AddInMemoryClients(Config.Clients);
    ​
                // not recommended for production - you need to store your key material somewhere secure
                builder.AddDeveloperSigningCredential();
            }
    ​
            public void Configure(IApplicationBuilder app)
            {
                if (Environment.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    ​
                // uncomment if you want to add MVC
                //app.UseStaticFiles();
                //app.UseRouting();
    ​
                app.UseIdentityServer();
    ​
                // uncomment, if you want to add MVC
                //app.UseAuthorization();
                //app.UseEndpoints(endpoints =>
                //{
                //    endpoints.MapDefaultControllerRoute();
                //});
            }
        }
    }

    参考资料

  • 相关阅读:
    教你怎么叠T恤
    最动人的情歌《The Power of Love》by Celine.Dion
    使代码简洁的 5 条忠告
    Timeout MessageBox
    内联函数
    局部对象
    const用法(转)
    心情
    内联函数
    局部对象
  • 原文地址:https://www.cnblogs.com/haogj/p/12591332.html
Copyright © 2020-2023  润新知