Asp.Net Core 中IdentityServer4 授权流程及刷新Token
一、前言
上面分享了IdentityServer4 兩篇系列文章,核心主題主要是密碼授權模式及自定義授權模式,但是僅僅是分享了這兩種模式的使用,這篇文章進一步來分享IdentityServer4的授權流程及refreshtoken。
系列文章目錄(沒看過的先看這幾篇文章再來閱讀本文章):
Asp.Net Core IdentityServer4 中的基本概念
Asp.Net Core 中IdentityServer4 授權中心之應用實戰
Asp.Net Core 中IdentityServer4 授權中心之自定義授權模式
為了繼續保持IdentityServer4 系列博客分享上下文一致,我這里再把上回授權中心拆分后的圖貼出來,如圖:
圖中的授權中心就是通過IdentityServer4實現的授權服務中心,我下面就直接用授權中心代替IdentityServer4的授權服務來繼續述說,也感謝大家對我的支持,一直閱讀我的文章。
二、授權流程
2.1 客戶端驗證流程圖
流程圖中,客戶端僅僅會到授權中心 請求一次,并拿到驗證公鑰返回給Api資源擁有端,后面客戶端再次嘗試請求Api資源時候就不會再到授權中心去獲取驗證公鑰,會直接用之前獲取到的公鑰進行驗證,驗證通過則授權通過。
2.2 授權及刷新refresh_token 流程圖
然而通過授權中心 獲取到的access_token 是有有效時間的,如果失效則需要通過refresh_token 重新到授權中心去刷新獲取最新的access_token,整體的流程圖如下:
客戶端攜帶上一次獲取到的access_token 請求受保護的Api資源時,通過公鑰進行驗證時發現access_token已經過期,則客戶端再攜帶refresh_token 向授權中心再次發起請求,刷新access_token以獲得最新的access_token和refresh_token,用最新的access_token 去獲取受保護的Api資源,這樣可以減少客戶端多次跳轉登錄授權頁面,提高用戶體驗。
三、應用實戰
說到例子,我這里不從零開始擼代碼, 還是在之前的代碼基礎上繼續改造代碼,在原有的定義客戶端的代碼中新增刷新access_token的相關配置,代碼如下:
public static IEnumerable<Client> GetClients() {return new List<Client>{new Client(){ClientId =OAuthConfig.UserApi.ClientId,AllowedGrantTypes = new List<string>(){GrantTypes.ResourceOwnerPassword.FirstOrDefault(),//Resource Owner Password模式GrantTypeConstants.ResourceWeixinOpen,},ClientSecrets = {new Secret(OAuthConfig.UserApi.Secret.Sha256()) },AllowOfflineAccess = true,//如果要獲取refresh_tokens ,必須把AllowOfflineAccess設置為trueAllowedScopes= {OAuthConfig.UserApi.ApiName,StandardScopes.OfflineAccess,},AccessTokenLifetime = OAuthConfig.ExpireIn,},};}如果你需要刷新access_token,則需要把AllowOfflineAccess設置true,同時添加StandardScopes.OfflineAccess 這個Scopes,主要代碼如下:
AllowOfflineAccess = true,//如果要獲取refresh_tokens ,必須把AllowOfflineAccess設置為true AllowedScopes= {OAuthConfig.UserApi.ApiName,StandardScopes.OfflineAccess,//如果要獲取refresh_tokens ,必須在scopes中加上OfflineAccess },授權中心,完整代碼如下:
OAuthMemoryData 代碼如下:
/// <summary> /// /// </summary> public class OAuthMemoryData {/// <summary>/// 資源/// </summary>/// <returns></returns>public static IEnumerable<ApiResource> GetApiResources(){return new List<ApiResource>{new ApiResource(OAuthConfig.UserApi.ApiName,OAuthConfig.UserApi.ApiName),};}public static IEnumerable<Client> GetClients(){return new List<Client>{new Client(){ClientId =OAuthConfig.UserApi.ClientId,AllowedGrantTypes = new List<string>(){GrantTypes.ResourceOwnerPassword.FirstOrDefault(),//Resource Owner Password模式GrantTypeConstants.ResourceWeixinOpen,},ClientSecrets = {new Secret(OAuthConfig.UserApi.Secret.Sha256()) },AllowOfflineAccess = true,//如果要獲取refresh_tokens ,必須把AllowOfflineAccess設置為trueAllowedScopes= {OAuthConfig.UserApi.ApiName,StandardScopes.OfflineAccess,},AccessTokenLifetime = OAuthConfig.ExpireIn,},};}/// <summary>/// 測試的賬號和密碼/// </summary>/// <returns></returns>public static List<TestUser> GetTestUsers(){return new List<TestUser>{new TestUser(){SubjectId = "1",Username = "test",Password = "123456"},};}/// <summary>/// 微信openId 的測試用戶/// </summary>/// <returns></returns>public static List<TestUser> GetWeiXinOpenIdTestUsers(){return new List<TestUser>{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<CookiePolicyOptions>(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<ClientStore>().AddResourceOwnerValidator<ResourceOwnerPasswordValidator>().AddExtensionGrantValidator<WeiXinOpenGrantValidator>();//添加微信端自定義方式的驗證#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 訪問授權中心 試一試,如下圖:訪問結果中已經包含了refresh_token和access_token等相關信息。
我們再來通過access_token 訪問Api資源(上兩篇有相關代碼,未閱讀上兩篇先去查閱)這里我就直接攜帶access_token去訪問,如圖:
訪問成功!!
我們再來刷新下refresh_token ,訪問如圖:
刷新refresh_token成功。我們到這里再來做一個小小的測試,測試上面的授權流程中的,第4,5 步,上面說到第4步主要是客戶端第一次請求Api資源時會向ids4服務網關去請求獲取驗證公鑰, 獲取成功返回給Api資源并存儲在內存中,后續不再會到ids4服務去獲取驗證公鑰
我們把上面的授權中心 (ids4服務網關)停止運行,再來用之前的access_token請求Api資源,如下圖:現在已經確定授權中心(ids4服務網關)確實停止了,不能訪問了,那我們再來通過之前未過期的access_token來請求Api資源網關,結果如下圖:
完美,請求還是成功,這完全證明:客戶端請求Api資源網關(受保護的資源)時,第一次收到請求會到授權中心(ids4服務網關)獲取驗證公鑰,并保持到內存中,后面的請求不會再到授權中心去獲得驗證公鑰,而是Api資源網關(受保護的資源)中直接通過保存下來的驗證公鑰進行驗證,從而通過授權。
·end·
dotNET博士
長按關注,一起學習分享技術
??給個[在看],是對我最大的支持??
總結
以上是生活随笔為你收集整理的Asp.Net Core 中IdentityServer4 授权流程及刷新Token的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 跟着“土牛”学架构知识
- 下一篇: 玩转控件:重写/重绘Dev中Messag