IdentityServer4实战这个系列主要介绍一些在IdentityServer4(后文称:ids4),在实际使用过程当中容易出现的问题,以及使用技巧,不按期更新,谢谢你们关注。使用过ids4的朋友应该知道,能够经过设置AccessTokenLifetime
属性,来控制AccessToken的存活时间,可是细心的朋友可能会发现,Token到期了依然能经过受权,这是怎么回事呢,下面我带你们一块儿来揭开神秘面纱。html
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在哪里吧。服务器
咱们在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获取到了信息:
这是怎么回事呢,和咱们想的有点不同,请听下节分解!
有这样的场景,若是你的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的,这里须要注意。
默认过时时间咱们能够经过JwtBearerOptions
对象的TokenValidationParameters
属性的ClockSkew
属性来获取。
能够看见默认的时间偏移为5分钟,那么如何来自定义这个值呢。
咱们能够经过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