IdentityServer4實戰 - AccessToken 生命週期分析

一.前言

IdentityServer4實戰這個系列主要介紹一些在IdentityServer4(後文稱:ids4),在實際使用過程當中容易出現的問題,以及使用技巧,不按期更新,謝謝你們關注。使用過ids4的朋友應該知道,能夠經過設置AccessTokenLifetime屬性,來控制AccessToken的存活時間,可是細心的朋友可能會發現,Token到期了依然能經過受權,這是怎麼回事呢,下面我帶你們一塊兒來揭開神祕面紗。html

二.關於 ID Token 和 AccessToken

Openid Connect(後文稱:OIDC)是在OAuth2.0協議上進行了擴展,OIDC=Identity+OAuth2.0,使其擁有身份認證+受權的能。它在OAuth2上構建了一個身份層,是一個基於OAuth2協議的身份認證標準協議。咱們都知道OAuth2是一個受權協議,它沒法提供完善的身份認證功能,OIDC使用OAuth2的受權服務器來爲第三方客戶端提供用戶的身份認證,並把對應的身份認證信息傳遞給客戶端,且能夠適用於各類類型的客戶端(好比服務端應用,移動APP,JS應用),且徹底兼容OAuth2,也就是說你搭建了一個OIDC的服務後,也能夠看成一個OAuth2的服務來用。應用場景如圖:git

OAuth2提供了Access Token來解決受權第三方客戶端訪問受保護資源的問題;OIDC在這個基礎上提供了ID Token來解決第三方客戶端標識用戶身份認證的問題。OIDC的核心在於在OAuth2的受權流程中,一併提供用戶的身份認證信息(ID Token)給到第三方客戶端,ID Token使用JWT格式來包裝,得益於JWT(JSON Web Token)的自包含性,緊湊性以及防篡改機制,使得ID Token能夠安全的傳遞給第三方客戶端程序而且容易被驗證。此外還提供了UserInfo的接口,用戶獲取用戶的更完整的信息。github

簡而言之ID Token就是JWT格式的數據,包含一我的類用戶的身份認證的信息,一個ID Token的例子以下:json

{
     "iss": "https://server.example.com",
     "sub": "24400320",
     "aud": "s6BhdRkqt3",
    "nonce": "n-0S6_WzA2Mj",
     "exp": 1311281970,
    "iat": 1311280970,
     "auth_time": 1311280969,
     "acr": "urn:mace:incommon:iap:silver"
 }

看到上面的數據是否是感受很熟悉,這是一個咱們從ids4申請的"AccessToken":api

eyJhbGciOiJSUzI1NiIsImtpZCI6IjhlM2U2MWY1ZWUyZDgwMGNlYjE2NmE5NGRjODczMTY0IiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MjU1Nzg3MTUsImV4cCI6MTUyNTU3ODcxNiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJhcGkxIl0sImNsaWVudF9pZCI6InJvLmNsaWVudCIsInN1YiI6IjEiLCJhdXRoX3RpbWUiOjE1MjU1Nzg3MTUsImlkcCI6ImxvY2FsIiwic2NvcGUiOlsiYXBpMSJdLCJhbXIiOlsicHdkIl19.JXU4bXUqf8QD4zQz61XC2WTKURtNIVhH23zQPJzOmEtYbQvO2oRP58sCfDQxADeImZ7O0vH4YXIfL8j60B-sAYJev7c2hnjVhHTJ0t-0bUPlLs43cqNG6RarZ8FyfHyhrvIwYBpJXKNROfr6GfLb4Vdpw4ZEd4AC2k2tHuKMfyrrTzqS0oUs1RwqH7KZ1W7pXDr_V2L4PjgCqOQelXAB_V5YXzR9E52FIXnKNzCVnWHmhiTSWg-ptONOoHss1a-ElWejXskTlMBQitnxSno05s4O6vp5R8zqMuo3j57SnPZVaTuR4AUVpDdVmFF9x9k-fHuXyqarsW6YGsXgTTA2Lw

咱們將上面的Token解碼能夠看見:安全

我想不用我多說,就能夠看見咱們的ID Token在哪裏吧。服務器

三.設置AccessToken過時時間

咱們在ids端設置咱們的客戶端資源的時候有一個AccessTokenLifetime屬性,此屬性能夠設置咱們申請的Token的有效時間,單位是秒,默認3600秒也就是一個小時。網絡

代碼示例:ui

new Client
{
    ClientId = "ro.client",
    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
    AccessTokenLifetime = 5,
    ClientSecrets = 
    {
        new Secret("secret".Sha256())
    },
    AllowedScopes = { "api1" }
}

本文所用代碼,爲ids4文檔中,第二個QuickStart,文末會給出地址。設計

Client對象還包含一個IdentityTokenLifetime屬性,是用來設置ID Token的存活時間,可是,咱們得到AccessToken之後,訪問API資源等,是用的受權,此屬性沒法影響AccessToken的有效期,這也是我在上面解釋了ID Token和AccessToken的區別的緣由,但願你們不要搞混淆了。

咱們上面將AccessToken的存活時間設置爲5s,咱們修改客戶端的代碼改一下,讓他暫停6s再次去訪問APi資源,看看會發生什麼:

咱們先看看返回的AccessToken信息裏,過時時間已經變成了5s:

看看暫停以後的結果:

能夠看到,原本Token應該過時沒法訪問的,可是仍是成功訪問API獲取到了信息:

這是怎麼回事呢,和咱們想的有點不同,請聽下節分解!

四.時間偏移(ClockSkew )

有這樣的場景,若是你的AccessToken還有5s過時,這時你經過這個AccessToken去訪問API資源,可是這時網絡堵塞,可能請求10s纔到達目標,那這時怎麼辦?若是須要保持所持有的AccessToken一直有效,是否須要提早刷新或者再次申請AccessToken?若是你本地的時間和API資源服務的時間具備時間差別多是幾秒,幾十秒等等,那麼你該如何判斷你所持有的AccessToken的有效性?

上述的這些問題,都是咱們將時間理想化了,因此當咱們的API資源受到請求根據AccessToken進行驗證的時候,會有一個時間偏移,通俗的講就是將AccessToken的邏輯過時時間日後推遲了,這個時間默認是5分鐘。好比咱們的AccessToken應該在2018年5月6日16:50:55過時,那麼實際上在API資源進行驗證的時候,容忍在過時時間後的五分鐘之內,此AccessToken依然是有效的,即在API資源驗證時,此AccessToken的真正過時時間爲2018年5月6日16:55:55,這個時間差就是用來解決上述問題的。這也是爲何上面咱們將AccessToken設置5s過時,但實際上5s以後還能用它成功訪問API。

此設置是針對於JWT的,這裏須要注意。

五.設置時間偏移

1.獲取默認過時時間

默認過時時間咱們能夠經過JwtBearerOptions對象的TokenValidationParameters屬性的ClockSkew屬性來獲取。

能夠看見默認的時間偏移爲5分鐘,那麼如何來自定義這個值呢。

2.設置時間偏移

咱們能夠經過IdentityServerAuthenticationOptions對象提供JwtValidationClockSkew屬性來自定義時間偏移,這個設置是在API資源的,由於當咱們請求API資源的時候,是API資源自行進行驗證的。

代碼以下:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore()
        .AddAuthorization()
        .AddJsonFormatters();
    services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = "http://localhost:5000";
            options.RequireHttpsMetadata = false;
            options.JwtValidationClockSkew = TimeSpan.FromSeconds(0);
            options.ApiName = "api1";
        });
}

咱們經過options.JwtValidationClockSkew = TimeSpan.FromSeconds(0);將這個時間偏移設置爲了0s,那麼咱們如今再運行咱們前面的程序,設置AccessToken過時時間爲5s,咱們暫停6s,會發生什麼。

能夠看到提示「Unauthorized」,能夠看到如今的狀況和咱們前面所想的狀況一致了。這就是時間偏移的做用。

六.寫在最後

在實際生產環境中,必定要儘可能保持各個服務,各個節點的時間同步,使用標準時間。而後這個時間偏移如沒有特殊需求不建議去更改它,這個就是這樣設計的,官方也是不推薦去更改它。若是設置太短可能引發文章說的問題哦。歡迎你們加入QQ羣(4656606)和我一塊兒交流,寫本文也是羣裏許多朋友問過這個問題,之前一直沒注意,今天才算解開了它的祕密。

本文所用代碼下載:

https://github.com/stulzq/IdentityServer4.Samples/tree/master/Practice/02_AccessTokenLifetime

參考資料:

相關文章
相關標籤/搜索