php从cert中获取公钥_.Net Core 中IdentityServer4、Token的应用小知识

一、前言

上面分享了IdentityServer4 两篇系列文章,核心主题主要是密码授权模式及自定义授权模式,但是仅仅是分享了这两种模式的使用,这篇文章进一步来分享IdentityServer4的授权流程及refreshtoken。

系列文章目录(没看过的先看这几篇文章再来阅读本文章):

  • Asp.Net Core IdentityServer4 中的基本概念
  • Asp.Net Core 中IdentityServer4 授权中心之应用实战
  • Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式

为了继续保持IdentityServer4 系列博客分享上下文一致,我这里再把上回授权中心拆分后的图贴出来,如图:

197da45f8b1dc6a91301a18b5d93d8be.png

图中的授权中心就是通过IdentityServer4实现的授权服务中心,我下面就直接用授权中心代替IdentityServer4的授权服务来继续述说,也感谢大家对我的支持,一直阅读我的文章。

二、授权流程

2.1 客户端验证流程图

b57bf7245105ca1fecc81ff3f9f30378.png

流程图中,客户端仅仅会到授权中心 请求一次,并拿到验证公钥返回给Api资源拥有端,后面客户端再次尝试请求Api资源时候就不会再到授权中心去获取验证公钥,会直接用之前获取到的公钥进行验证,验证通过则授权通过。

2.2 授权及刷新refresh_token 流程图

然而通过授权中心 获取到的access_token 是有有效时间的,如果失效则需要通过refresh_token 重新到授权中心去刷新获取最新的access_token,整体的流程图如下:

ed1a3ac45fe941bd9deaca4e9f70d640.png

客户端携带上一次获取到的access_token 请求受保护的Api资源时,通过公钥进行验证时发现access_token已经过期,则客户端再携带refresh_token 向授权中心再次发起请求,刷新access_token以获得最新的access_token和refresh_token,用最新的access_token 去获取受保护的Api资源,这样可以减少客户端多次跳转登录授权页面,提高用户体验。

三、应用实战

说到例子,我这里不从零开始撸代码, 还是在之前的代码基础上继续改造代码,在原有的定义客户端的代码中新增刷新access_token的相关配置,代码如下:

public static IEnumerable GetClients(){     return new List     {         new Client()         {             ClientId =OAuthConfig.UserApi.ClientId,             AllowedGrantTypes = new List()             {                 GrantTypes.ResourceOwnerPassword.FirstOrDefault(),//Resource Owner Password模式                 GrantTypeConstants.ResourceWeixinOpen,             },             ClientSecrets = {new Secret(OAuthConfig.UserApi.Secret.Sha256()) },             AllowOfflineAccess = true,//如果要获取refresh_tokens ,必须把AllowOfflineAccess设置为true             AllowedScopes= {                 OAuthConfig.UserApi.ApiName,                 StandardScopes.OfflineAccess,             },             AccessTokenLifetime = OAuthConfig.ExpireIn,         },      }; }

如果你需要刷新access_token,则需要把AllowOfflineAccess设置true,同时添加StandardScopes.OfflineAccess 这个Scopes,主要代码如下:

AllowOfflineAccess = true,//如果要获取refresh_tokens ,必须把AllowOfflineAccess设置为trueAllowedScopes= {     OAuthConfig.UserApi.ApiName,     StandardScopes.OfflineAccess,//如果要获取refresh_tokens ,必须在scopes中加上OfflineAccess},

授权中心,完整代码如下:

OAuthMemoryData 代码如下:

/// /// /// public class OAuthMemoryData{        ///         /// 资源        ///         ///         public static IEnumerable GetApiResources()        {            return new List            {                new ApiResource(OAuthConfig.UserApi.ApiName,OAuthConfig.UserApi.ApiName),            };        }        public static IEnumerable GetClients()        {            return new List            {                new Client()                {                    ClientId =OAuthConfig.UserApi.ClientId,                    AllowedGrantTypes = new List()                    {                        GrantTypes.ResourceOwnerPassword.FirstOrDefault(),//Resource Owner Password模式                        GrantTypeConstants.ResourceWeixinOpen,                    },                    ClientSecrets = {new Secret(OAuthConfig.UserApi.Secret.Sha256()) },                    AllowOfflineAccess = true,//如果要获取refresh_tokens ,必须把AllowOfflineAccess设置为true                    AllowedScopes= {                        OAuthConfig.UserApi.ApiName,                        StandardScopes.OfflineAccess,                    },                    AccessTokenLifetime = OAuthConfig.ExpireIn,                },            };        }        ///         /// 测试的账号和密码        ///         ///         public static List GetTestUsers()        {            return new List            {                new TestUser()                {                     SubjectId = "1",                     Username = "test",                     Password = "123456"                },            };        }        ///         /// 微信openId 的测试用户        ///         ///         public static List GetWeiXinOpenIdTestUsers()        {            return new List            {                new TestUser(){                  SubjectId="owerhwroogs3902openId",                }            };        }    }

Startup 完整代码如下:

 public class Startup {        public Startup(IConfiguration configuration)        {            Configuration = configuration;        }        public IConfiguration Configuration { get; }        // This method gets called by the runtime. Use this method to add services to the container.        public void ConfigureServices(IServiceCollection services)        {            services.AddControllers();            services.Configure(options =>            {                // This lambda determines whether user consent for non-essential cookies is needed for a given request.                options.CheckConsentNeeded = context => true;                options.MinimumSameSitePolicy = SameSiteMode.None;            });            #region 内存方式            //services.AddIdentityServer()            //    .AddDeveloperSigningCredential()            //    .AddInMemoryApiResources(OAuthMemoryData.GetApiResources())            //    .AddInMemoryClients(OAuthMemoryData.GetClients())            //    .AddTestUsers(OAuthMemoryData.GetTestUsers());            #endregion            #region 数据库存储方式            services.AddIdentityServer()                .AddDeveloperSigningCredential()                .AddInMemoryApiResources(OAuthMemoryData.GetApiResources())                //.AddInMemoryClients(OAuthMemoryData.GetClients())                .AddClientStore()                .AddResourceOwnerValidator()                .AddExtensionGrantValidator();//添加微信端自定义方式的验证            #endregion        }        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            app.UseIdentityServer();            app.UseRouting();            app.UseAuthorization();            app.UseEndpoints(endpoints =>            {                endpoints.MapControllers();            });        }    }

授权中心代码基本上已经改造完成,我们用postman 访问授权中心 试一试,如下图:

568f13f3ed6d93a27e348e90a0bb69b0.png

访问结果中已经包含了refresh_token和access_token等相关信息。

我们再来通过access_token 访问Api资源(上两篇有相关代码,未阅读上两篇先去查阅)这里我就直接携带access_token去访问,如图:

fc74d57f998b4b88c5cc3d03fd03d8a3.png

访问成功!!

我们再来刷新下refresh_token ,访问如图:

7dbb8056d56794e575db82bb890c44f8.png

刷新refresh_token成功。我们到这里再来做一个小小的测试,测试上面的授权流程中的,第4,5 步,上面说到第4步主要是客户端第一次请求Api资源时会向ids4服务网关去请求获取验证公钥,
获取成功返回给Api资源并存储在内存中,后续不再会到ids4服务去获取验证公钥

我们把上面的授权中心 (ids4服务网关)停止运行,再来用之前的access_token请求Api资源,如下图:

08799bc35052622e4fc89396a3a356a0.png

现在已经确定授权中心(ids4服务网关)确实停止了,不能访问了,那我们再来通过之前未过期的access_token来请求Api资源网关,结果如下图:

d41556eedbafb8539b319dc40436b0b7.png

完美,请求还是成功,这完全证明:客户端请求Api资源网关(受保护的资源)时,第一次收到请求会到授权中心(ids4服务网关)获取验证公钥,并保持到内存中,后面的请求不会再到授权中心去获得验证公钥,而是Api资源网关(受保护的资源)中直接通过保存下来的验证公钥进行验证,从而通过授权

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值