• 【WebAPI No.3】API的访问控制IdentityServer4


    介绍:

    IdentityServer是一个OpenID Connect提供者 - 它实现了OpenID Connect和OAuth 2.0协议。是一种向客户发放安全令牌的软件。

    官网给出的功能解释是:

    • 保护您的资源
    • 使用本地帐户存储或通过外部身份提供商对用户进行身份验证
    • 提供会话管理和单点登录
    • 管理和认证客户
    • 向客户发布身份和访问令牌
    • 验证令牌

    IdentityServe4的四种模式:

    • 授权码模式(authorization code)
    • 简化模式(implicit)
    • 密码模式(resource owner password credentials)
    • 客户端模式(client credentials)

    以下是IdentityServer的一个大致流程图:

    注册IdentityServe4认证服务器:

    先在asp.net core我们选中空模版。因为本身写的业务也不多,只是为了做token的认证处理,所有建这个做测试比较方便。

    创建代码示例:

    什么时候都不要忘记添加引用哦:

    NuGet命令行:Install-Package IdentityServer4

    当然你也可以这样:

    然后创建config.cs类来处理我们的一些业务:

     //定义范围
            #region 定义要保护的资源(webapi)
            public static IEnumerable<ApiResource> GetApiResources()
            {
                return new List<ApiResource>
                {
                    new ApiResource("FirstAPI", "API接口安全测试")
                };
            }
            #endregion
    
            #region 定义可访问客户端
            public static IEnumerable<Client> GetClients()
            {
                return new List<Client>
                {
                    new Client
                    {
                        //客户端id自定义
                        ClientId = "YbfTest",
    
                        AllowedGrantTypes = GrantTypes.ClientCredentials, ////设置模式,客户端模式
    
                        // 加密验证
                        ClientSecrets = new List<Secret>
                        {
                            new Secret("secret".Sha256())
                        },
    
                        // client可以访问的范围,在GetScopes方法定义的名字。
                        AllowedScopes = new List<string>
                        {
                            "FirstAPI"
                        }
                    }
                };
            } 
            #endregion
    View Code

    以上就是一个基本的处理类了。然后我们开始在Startup.cs 配置IdentityServer4

     public void ConfigureServices(IServiceCollection services)
            {
                services.AddIdentityServer()
                     .AddDeveloperSigningCredential()
                     .AddInMemoryApiResources(Config.GetApiResources())  //配置资源               
                     .AddInMemoryClients(Config.GetClients());//配置客户端
            }
    View Code
     public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                //将IddiTyServer添加到管道中。
                app.UseIdentityServer();
    
                app.Run(async (context) =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            }
    View Code

    这样就可以启动项目了,确认项目启动完成后,还要确认服务是否开启成功:在地址后增加地址:/.well-known/openid-configuration 例如:

    出现以上结果就是启动成功了。

    当然你也可以使用postMan测试工具测试:

    需要输入

    • grant_type为客户端授权client_credentials,
    • client_idConfig中配置的ClientId
    • Client_Secret为Config中配置的Secret

    例如:

     创建webAPI资源服务器

    这个比较简单了,首先创建一个简单的webapi程序即可。

    还是老规矩咯iuput,什么时候都不要忘记引用:

    通过nuget添加即可:IdentityServer4.AccessTokenValidation

    然后点击确定安装就可以了。

    主要认证注册服务:

    在Startup类里面的ConfigureServices方法里面添加注册

            public void ConfigureServices(IServiceCollection services)
            {
                //注册IdentityServer 
                services.AddAuthentication(config => {
                    config.DefaultScheme = "Bearer"; //这个是access_token的类型,获取access_token的时候返回参数中的token_type一致
                }).AddIdentityServerAuthentication(option => {
                    option.ApiName = "FirstAPI"; //资源名称,认证服务注册的资源列表名称一致,
                    option.Authority = "http://127.0.0.1:5000"; //认证服务的url
                    option.RequireHttpsMetadata = false; //是否启用https
    
                });
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            }

    然后在在Startup的Configure方法里配置Authentication中间件:

               //配置Authentication中间件
                app.UseAuthentication();

    然后添加一个控制器进行验证测试:

    我这里写了一个获取value值简单检测一下。

     // GET api/values
            [HttpGet]
            [Authorize]
            public ActionResult<IEnumerable<string>> Get()
            {
                return new string[] { "value1", "value2" };
            }

    这里注意要添加[Authorize]特性。用来做验证是否有权限的。没有的话,以上做的没有意义。需要引用命名空间:using Microsoft.AspNetCore.Authorization;

    看一下正确的请求结果:

    如果不传token值请求:

    注意这里就会返回401的未授权状态。 

    创建Client(客户端)

    上面我们使用的是postman请求的以演示程序是否创建成功,这里我们假设一个用户的使用客户端,这里我们创建一个控制台来模拟一下真实的小场景。

    既然是控制台就没什么好说的直接上代码main函数:

    Task.Run(async () =>
                {
                    //从元数据中发现终结点,查找IdentityServer
                    var disco = await DiscoveryClient.GetAsync("http://127.0.0.1:5000");
                    if (disco.IsError)
                    {
                        Console.WriteLine(disco.Error);
                        return;
                    }
    
                    //向IdentityServer请求令牌
                    var tokenClient = new TokenClient(disco.TokenEndpoint, "YbfTest", "YbfTest123");//请求的客户资源
                    var tokenResponse = await tokenClient.RequestClientCredentialsAsync("FirstAPI");//运行的范围
    
                    if (tokenResponse.IsError)
                    {
                        Console.WriteLine(tokenResponse.Error);
                        return;
                    }
    
                    Console.WriteLine(tokenResponse.Json);
    
                    //访问Api
                    var client = new HttpClient();
                    //把令牌添加进请求
                    //client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",tokenResponse.AccessToken);
                    //client.SetBearerToken(tokenResponse.AccessToken);
                    client.SetToken("Bearer", tokenResponse.AccessToken);
    
                    var response = await client.GetAsync("http://localhost:42033/api/values");
                    if (!response.IsSuccessStatusCode)
                    {
                        Console.WriteLine(response.StatusCode);
                    }
                    else
                    {
                        var content = await response.Content.ReadAsStringAsync();
                        Console.WriteLine(JArray.Parse(content));
                    }
                });
    
                Console.ReadLine();
    View Code

    这里主要介绍一下请求资源时添加令牌主要有三种形式,我都在代码给出,根据api资源的注册形式选择适合的。api的注册我也写了两种形式。主要的区别就是token前面的Bearer,如果想写成自定义的和默认成Bearer就是这里的区分。

    自定义就要使用:

    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",tokenResponse.AccessToken);

    如果全局默认的形式就不比每次请求都要添加所以可以写成:

    client.SetBearerToken(tokenResponse.AccessToken);

    运行项目之后出现成功界面:

     

     传送门

    WebApi系列文章目录介绍

  • 相关阅读:
    ORA-28001 has expired错误密码过期问题
    Oracle数据库无用户名密码登录
    使用Navicat连接Oracle数据库出现12541或者28547错误代码
    Solr的helloWord程序
    JS工具方法
    python发送邮件
    jmeter的性能监控框架搭建记录(Influxdb+Grafana+Jmeter)
    spotlight on mysql 监控
    linux下安装python环境
    yum的方式搭建mysql
  • 原文地址:https://www.cnblogs.com/yanbigfeg/p/9227754.html
Copyright © 2020-2023  润新知