zoukankan      html  css  js  c++  java
  • Identity Server4学习系列四之用户名密码获得访问令牌

    1、简介

    Identity Server4支持用户名密码模式,允许调用客户端使用用户名密码来获得访问Api资源(遵循Auth 2.0协议)的Access Token,MS可能考虑兼容老的系统,实现了这个功能,但是不建议这么做.

    2、实战一服务端配置

    接着Identity Server4学习系列三的基础上,直接扩展里面的项目代码,让服务端同时支持密钥认证和用户名密码认证

    第一步:扩展ThirdClients类,如下:

        /// <summary>
        /// 配置可以访问IdentityServer4 保护的Api资源模型的第三方客户端
        /// 配置客户端访问的密钥
        /// </summary>
        public class ThirdClients
        {
            public static IEnumerable<Client> GetClients()
            {
                return new List<Client>()
                {
                    new Client()
                    {
                        //客户端的唯一Id,客户端需要指定该ClientId才能访问
                         ClientId = $"client",
    
                        //no interactive user, use the clientid/secret for authentication
                        //使用客户端密钥进行认证
                        AllowedGrantTypes = GrantTypes.ClientCredentials,
    
                        // 认证密钥,客户端必须使用secret密钥才能成功访问
                        ClientSecrets =
                        {
                            //用Sha256对"secret"进行加密
                            new Secret("secret".Sha256())
                        },
    
                        // scopes that client has access to
                        //如果客户端的密钥认证成功,限定该密钥可以访问的Api范围
                        AllowedScopes = { "api1" }
                    },
                    //添加支持用户名密码模式访问的客户端类型
                    new Client()
                    {
                        ClientId = "userPwd.client",
                        AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
    
                        ClientSecrets =
                        {
                            new Secret("secret".Sha256())
                        },
                        AllowedScopes = { "api1" }
                    }
                };
            }
    
            /// <summary>
            /// 配置可以访问IdentityServer4 保护的Api资源模型的第三方客户端
            /// 使用用户名密码模式
            /// </summary>
            /// <returns></returns>
            public static List<TestUser> GetUsers()
            {
                return new List<TestUser>()
                {
                    new TestUser()
                    {
                        SubjectId = "1",
                        Username = "alice",
                        Password = "password"
                    }
                };
            }
        }

    第二步:注册TestUser到Identity Server4,修改StartUp文件如下:

        public class Startup
        {
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                //优雅的链式编程
                //注入Identity Server4服务到DI容器中
                services.AddIdentityServer()
               //注入临时签名凭据到DI容器,后期可用签名证书的密钥替换,用于生成零时密钥
               .AddDeveloperSigningCredential()
               //注入需要受Identity Server4保护的Api资源添注入到DI容器中 -内存级别
               .AddInMemoryApiResources(Apis.GetApiResources())
               //注入需要访问受Identity Server4保护的Api资源的客户端(密钥模式)注入到DI容器中 -内存级别
               .AddInMemoryClients(ThirdClients.GetClients())
               //注入需要访问受Identity Server4保护的Api资源的客户端(用户名密码访问模式)注入到DI容器中 -内存级别
               .AddTestUsers(ThirdClients.GetUsers());
    
                //注入基本的MVC服务
                services.AddMvcCore()
                //注入MVC的认证服务,对应控制器的Authorize特性
               .AddAuthorization()
               //注入MVC格式化程序,对应JsonResult等等的格式化操作,主要用于控制器返回值的格式化操作
               .AddJsonFormatters();
    
                //注入身份认证服务,设置Bearer为默认方案
                services.AddAuthentication("Bearer")
                //注入并配置Bearer为默认方案的基本参数
                .AddIdentityServerAuthentication(options =>
                {
                    //设置令牌的发布者
                    options.Authority = "http://localhost:5000";
                    //设置Https
                    options.RequireHttpsMetadata = false;
                    //需要认证的api资源名称
                    options.ApiName = "api1";
                });
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                //如果当前时开发者模式
                if (env.IsDevelopment())
                {
                    //从管道中捕获同步和异步System.Exception实例并生成HTML错误响应。
                    app.UseDeveloperExceptionPage();
                }
    
                //将IdentityServer 4服务注入到管道模型中(对应上面的IdentityServer 4服务的配置)
                app.UseIdentityServer();
    
                //将认证服务通过Microsoft.AspNetCore.Authentication.AuthenticationMiddleware中间件
                //注入到管道模型中(对应上面认证服务的配置)
                app.UseAuthentication();
    
                //将mvc添加到Microsoft.AspNetCore.Builder.IApplicationBuilder请求执行中(对应上的MVC配置)
                app.UseMvc();
            }
        }

    ok,到这一步,Identity Server4服务端配置完成!

    3、实战一客户端发起调用

    调用代码如下:

        class Program
        {
            static void Main(string[] args)
            {
                Request();
                Console.ReadKey();
            }
    
            async static void Request()
            {
                //请求Identity Server4服务
                var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
                if (disco.IsError)
                {
                    Console.WriteLine(disco.Error);
                    return;
                }
                var tokenClient = new TokenClient(disco.TokenEndpoint, "userPwd.client", "secret");
                var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("alice", "password", "api1");
    
                if (tokenResponse.IsError)
                {
                    Console.WriteLine(tokenResponse.Error);
                    return;
                }
                //通过Identity Server4的认证过后,拿到AccessToken
                var client = new HttpClient();
                client.SetBearerToken(tokenResponse.AccessToken);
                var response = await client.GetAsync("http://localhost:5000/identity");
                if (!response.IsSuccessStatusCode)
                {
                    Console.WriteLine(response.StatusCode);
                }
                else
                {
                    //认证成功,输出Identity控制器的返回值
                    var content = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(JArray.Parse(content));
                }
                Console.WriteLine(tokenResponse.Json);
                Console.WriteLine("
    
    ");
            }
        }

    ok,使用用户名加密钥模式,访问Api成功拿到Api返回值,注意密钥任然需要给,因为这个密钥是用与给Token加密的,而用户名和密码无非是继续加一了一层认证,如果密钥认证成功,必须进行用户名和密码的认证,两者必须同时认证成功,才能成功的发起Api的调用.

    用户名和密码必须和服务端给定的一致,否则客户端会报这个错:

    无效的授权.

    至此,用户名密码加密钥模式介绍完毕!

  • 相关阅读:
    LeetCode 152. 乘积最大子数组 | Python
    LeetCode 31. 下一个排列 | Python
    LeetCode 136. 只出现一次的数字 | Python
    LeetCode 102. 二叉树的层序遍历 | Python
    LeetCode 155. 最小栈 | Python
    LeetCode 69. x 的平方根 | Python
    Python3 高阶函数
    Python3 装饰器
    Python3 递归函数
    Python3 函数
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/10124365.html
Copyright © 2011-2022 走看看