zoukankan      html  css  js  c++  java
  • 【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系列文章目录介绍

  • 相关阅读:
    mysql 远程登陆不上
    hdu 5339 Untitled【搜索】
    SqlServer 书目
    passwordauthentication yes
    oracle 11g RAC ocfs2
    Oracle 11g RAC database on ASM, ACFS or OCFS2
    CentOS ips bonding
    Oracle 11g RAC features
    openStack 王者归来之 trivial matters
    openstack windows 2008 img
  • 原文地址:https://www.cnblogs.com/yanbigfeg/p/9227754.html
Copyright © 2011-2022 走看看