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("\n\n");
        }
    }

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

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

无效的授权.

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

原文地址:https://www.cnblogs.com/GreenLeaves/p/10124365.html

时间: 2024-10-12 10:24:25

Identity Server4学习系列四之用户名密码获得访问令牌的相关文章

Identity Server4学习系列三

1.简介 在Identity Server4学习系列一和Identity Server4学习系列二之令牌(Token)的概念的基础上,了解了Identity Server4的由来,以及令牌的相关知识,本文开始实战,实现Identity Server4基本的功能. 2.前提 本文基于.Net Core2.1和Indetity Server4 2.3.0,令牌处理包采用IdentityServer4.AccessTokenValidation 2.7.0 3.实战一Identity Server4服

weblogic学习笔记(五)----无需用户名密码启动Server

一. 新建security文件夹 # cd $WEBLOGIC_HOME/servers/Server-0 # mkdir security 二. 创建boot.properties文件 # vi boot.properties 三.填写用户名密码 username=weblogic password=weblogic12 四. 启动server # cd $WEBLOGIC_HOME/bin # ./startManagedWebLogic.sh Server-0 可以看到,不再需要手动输入管

Android SDK范例源码学习系列四 AppNavigation

 (本系列基于Jelly Bean,Android OS4.2,API 17版本) 就算是最简单的应用程序也会拥有不止一项功能,因此我们经常要应对多个Activity.主Activity随应用程序启动而启动,可以通过触发事件开启另外的Activity.要想激活应用中的某个特定组件,可以用显式命名的Intent来实现,也可以采用隐式Intent,尽可能选用隐式的,它能为模块化功能提供强大的框架. 隐式Intent不需要指定要使用哪个组件,它们通过过滤器指定所需的功能,而Android系统必须决定使

Vue学习系列(四)——理解生命周期和钩子

前言 在上一篇中,我们对平时进行vue开发中遇到的常用指令进行归类说明讲解,大概已经学会了怎么去实现数据绑定,以及实现动态的实现数据展示功能,运用指令,可以更好更快的进行开发.而在这一篇中,我们将通过实例,探究vue的生命周期. 万物皆有灵,世间万物都拥有灵魂,小到山河湖海,花草树木,蚂蚁到人类,以及所有的动植物,大到地球星空和宇宙,都拥有灵魂,可以说他们都是有生命的,只是他们的生命形态是我们人类所不能理解的存在.在生产中,生命周期通俗来讲,就是从自然中来回到自然中去的全过程,也就是从采集材料设

[jQuery学习系列四 ]4-Jquery学习四-事件操作

前言:今天看知乎偶然看到中国有哪些类似于TED的节目, 回答中的一些推荐我给记录下来了, 顺便也在这里贴一下: 一席 云集 听道 推酷 青年中国说 SELF格致论道 参考:http://www.365mini.com/page/tag/jquery-event-methods 1,readyready()函数用于在当前文档结构载入完毕后立即执行指定的函数.该函数的作用相当于window.onload事件. 2,blindbind()函数用于为每个匹配元素的一个或多个事件绑定事件处理函数.举例:

WCF学习系列四--【WCF Interview Questions – Part 4 翻译系列】

WCF Interview Questions – Part 4 This WCF service tutorial is part-4 in series of WCF Interview Questions. Before reading this please go through the following articles in this series. 这是WCF问答教程的第四部分,在阅读之前请先去看下面列出来的文章. WCF Service Interview Questions 

web多终端开发学习系列(四)--- web图表插件

对于数据的显示除了可以用表格外,还可以使用图表来更好.更直观地表达数据,比如数据的趋势可以用折线图,数据的比例可以用饼图等等.所以在web的开发过程中图表的应用非常广泛,对于图表的js框架我找到了Chart.js和Highcharts.Chart支持响应式布局,而Highcharts不支持,但是Highcharts的功能更全面. 介绍 Chart.js的官网是:http://www.bootcss.com/p/chart.js/,Chart.js不依赖于第三方类库,只需导入Chart.js即可.

scrapy爬虫学习系列四:portia的学习入门

portia的简介: Portia是我们的开源可视化爬虫工具,可让您在不需要任何编程知识的情况下爬取网站!简单地注释您感兴趣的页面,Portia将创建一个蜘蛛来从类似的页面提取数据 scrapyhub上的一些简介视频(需FQ): https://helpdesk.scrapinghub.com/support/solutions/articles/22000201027-learn-portia-video-tutorials- scrapyhub上的完整入门手册:https://helpdes

STL学习系列四:Stack容器

Stack简介 stack是堆栈容器,是一种“先进后出”的容器. stack是简单地装饰deque容器而成为另外的一种容器. #include <stack> 1.stack对象的默认构造 stack采用模板类实现, stack对象的默认构造形式: stack <T> stkT; stack <int> stkInt;            //一个存放int的stack容器. stack <float> stkFloat;     //一个存放float的