IdentityServer4之ClientCredentials(客户端凭据许可)


IdentityServer4ClientCredentials(客户端凭据许可)

 

1. 创建IdentityServer4服务

这里使用VS2019创建.net5.0框架下的IdentityServer4服务项目,命名为IdentityServer4_ClientCredentials”,端口设置为5001

通过Nuget安装IdentityServer4命令如下,记得程序包管理控制套,上面的项目选择刚刚创建的IdentityServer项目,代码如下:

Install-Package IdentityServer4 

2. 配置身份服务器

Defining an API Scope

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

创建Config.cs文件,代码如下所示:

 public static class Config

    {

        public static IEnumerable IdentityResources =>

     new IdentityResource[]

     {

                new IdentityResources.OpenId(),

                new IdentityResources.Profile()

     };

 

        // v4新增

        public static IEnumerable ApiScopes =>

            new ApiScope[] {

                 new ApiScope("OrderApi","Order Api")

            };

        public static IEnumerable Clients =>

            new Client[]

            { //客户端的唯一标识  此模式可用于前端

                new Client

                {

                   // 客户端的唯一标识

                   ClientId="client",

                   // 客户端认证密码

                   ClientSecrets = { new Secret("ordersecret".Sha256()) },

                   // 指定授权模式,这里指定为客户端凭据模式

                   AllowedGrantTypes = GrantTypes.ClientCredentials,

                   // 指定客户端获取的Token能访问到的作用域

                   AllowedScopes={ "OrderApi" }

                }};

}

引用命名空间:

using IdentityServer4.Models;

3. 配置身份服务器

 修改Startup.cs文件。

加载加载资源和客户端:代码如下:

public void ConfigureServices(IServiceCollection services)

        {

            // uncomment, if you want to add an MVC-based UI

            //services.AddControllersWithViews();

 

            var builder = services.AddIdentityServer(options =>

            {

                // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html

                options.EmitStaticAudienceClaim = true;

            })

                .AddInMemoryIdentityResources(Config.IdentityResources)

                .AddInMemoryApiScopes(Config.ApiScopes)

                .AddInMemoryClients(Config.Clients);

 

            // not recommended for production - you need to store your key material somewhere secure

            builder.AddDeveloperSigningCredential();

        }

身份验证服务添加到 DI(依赖注入)并将身份验证中间件添加到管道中

app.UseIdentityServer();

4. 创建WebAPI服务

这里创建一个订单服务,命名为OrderApi,端口为62274。

为控制器添加授权要求:

添加Microsoft.AspNetCore.Authentication.JwtBearer引用

注册认证相关组件和配置defaultSchemeBearer,代码:

services.AddAuthentication("Bearer")

                .AddJwtBearer("Bearer", options =>

                {

                    // 指定要接入的授权服务器地址

                    options.Authority = "http://localhost:5000";

                    // 在验证token时,不验证Audience

                    options.TokenValidationParameters = new TokenValidationParameters

                    {

                        ValidateAudience = false

                    };

                    // 不适用Https

                    options.RequireHttpsMetadata = false;

 

                });

SetupConfigure方法中添加认证和授权中间件,代码:

// 注册认证过滤器,在授权过滤器前面

            app.UseAuthentication();

            // 注册授权过滤器

            app.UseAuthorization();

5. 创建客户

创建WinFrom客户端,命名为WinFormsClient,在默认的Form1窗体中添加按钮和文本框用于调用接口和查看接口返回值,这里直接调用自带的温度接口。

代码如下:

private async void button1_Click(object sender, EventArgs e)

        {

            await Post();

        }

 

        private async Task Post()

        {

            // 1. 创建一个HttpClient用于请求

            var client = new HttpClient();

            // 2. 获取授权服务器的相关信息,IdentityModel已经将其封装好了

            var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");

            // 3. 检查是否请求错误

            if (disco.IsError)

            {

                // 错误就打印错误信息,然后直接返回

                textBox1.Text = disco.Error;

                return;

            }

            // 4. 通过授权服务分配的标识,向授权服务器请求AccessToken

            var tokenResp = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest

            {

                // 指定获取token的地址,IdentityModel进行封装,直接使用即可

                Address = disco.TokenEndpoint,

                // 指定授权服务器分配的客户端标识

                ClientId = "client",

                // 指定授权服务器分的客户端密码

                ClientSecret = "ordersecret"

            });

            // 5. 检查获取Token是否成功

            if (tokenResp.IsError)

            {

                // 如果失败,打印错误消息并返回

                textBox1.Text = tokenResp.Error;

                return;

            }

 

            // 6. 创建一个请求API资源的HttpClient

            var apiClient = new HttpClient();

            // 7. 将获取到的Token以Bearer的方案设置在请求头中

            apiClient.SetBearerToken(tokenResp.AccessToken);

            // 8. 向资源服务器中请求受保护的API

            var contentResp = await apiClient.GetAsync("http://localhost:62274/weatherforecast");

            // 9. 打印对应的消息

            if (contentResp.IsSuccessStatusCode)

            {

                var content = await contentResp.Content.ReadAsStringAsync();

                textBox1.Text = content;

            }

            else

            {

                textBox1.Text = contentResp.StatusCode.ToString();

            }

 

        }

6.调用接口

设置多启动项目,运行。

 

点击调用接口按钮:

 

 

 

鸣谢:

https://github.com/IdentityServer

https://mp.weixin.qq.com/s/5B22Q9yBYqFFDBzOWxeP7w

 

 

源码

https://github.com/yandaniugithub/NETCore

相关