IdentityServer4实战 - AccessToken 生命周期分析

一.前言

IdentityServer4实战这个系列主要介绍一些在IdentityServer4(后文称:ids4),在实际使用过程中容易出现的问题,以及使用技巧,不定期更新,谢谢大家关注。使用过ids4的朋友应该知道,可以通过设置AccessTokenLifetime属性,来控制AccessToken的存活时间,但是细心的朋友可能会发现,Token到期了依然能通过授权,这是怎么回事呢,下面我带大家一起来揭开神秘面纱。

二.关于 ID Token 和 AccessToken

Openid Connect(后文称:OIDC)是在OAuth2.0协议上进行了扩展,IODC=Identity+OAuth2.0,使其拥有身份认证+授权的能。它在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议。我们都知道OAuth2是一个授权协议,它无法提供完善的身份认证功能,OIDC使用OAuth2的授权服务器来为第三方客户端提供用户的身份认证,并把对应的身份认证信息传递给客户端,且可以适用于各种类型的客户端(比如服务端应用,移动APP,JS应用),且完全兼容OAuth2,也就是说你搭建了一个OIDC的服务后,也可以当作一个OAuth2的服务来用。应用场景如图:

OAuth2提供了Access Token来解决授权第三方客户端访问受保护资源的问题;OIDC在这个基础上提供了ID Token来解决第三方客户端标识用户身份认证的问题。OIDC的核心在于在OAuth2的授权流程中,一并提供用户的身份认证信息(ID Token)给到第三方客户端,ID Token使用JWT格式来包装,得益于JWT(JSON Web Token)的自包含性,紧凑性以及防篡改机制,使得ID Token可以安全的传递给第三方客户端程序并且容易被验证。此外还提供了UserInfo的接口,用户获取用户的更完整的信息。

简而言之ID Token就是JWT格式的数据,包含一个人类用户的身份认证的信息,一个ID Token的例子如下:

{
     "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":

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

我们将上面的Token解码可以看见:

我想不用我多说,就可以看见我们的ID Token在哪里吧。

三.设置AccessToken过期时间

我们在ids端设置我们的客户端资源的时候有一个AccessTokenLifetime属性,此属性可以设置我们申请的Token的有效时间,单位是秒,默认3600秒也就是一个小时。

代码示例:

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

参考资料:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏友弟技术工作室

如何在CLI上管理密码

基于密码的认证在网络盛行的今天,你可能需要或者已经使用了某种密码管理工具来跟踪管理你正在使用的所有密码。有各种各样的在线或离线服务或者软件工具用于完成此类事情,...

40911
来自专栏沈唁志

宝塔面板Mysql 5.6版本无法正常启动的解决方法

朋友找我的时候说的是 Mysql 启动不了,看他发的截图是宝塔面板,就要来了面板信息去看了一下

5612
来自专栏移动开发的那些事儿

IM二分法智能心跳策略

953
来自专栏Fred Liang

Service Worker 实现 web 应用消息推送

Service Worker 是事件驱动的 worker,生命周期与页面无关,关联页面未关闭时,它也可以退出,没有关联页面时,它也可以启动.

2532
来自专栏Python数据科学

爬虫模拟登录—OAUTH的详解

前两篇分享了HTTP的基本概念和高级用法,以及京东模拟登录的实战内容。本篇博主将会继续与大家分享HTTP中的另一个有趣内容:OAUTH,它也是在爬虫的模拟登录中...

1332
来自专栏张戈的专栏

解决dos2unix/unix2dos报错,并在家目录下生成u2dtmp*文件问题

最近接到一个 case:大数据分析那边反馈我们这边推送的数据同比去年同期少了很多。这是很不正常的,因为业务一直在增长。 ? 于是,我开始顺藤摸瓜的跟进。一开始就...

4516
来自专栏雨尘分享

手把手教你搭建微信小程序服务器(HTTPS)第一步:申请服务器与域名第二步:申请HTTPS 证书第三步:配置服务器第四步:上传文件第五步:域名备案第六步:小程序设置

1.1K5
来自专栏腾讯移动品质中心TMQ的专栏

Appium:轻松玩转app+webview混合应用自动化测试

Appium这个听起来既生疏也熟悉的自动化测试工具,比起原生的UiAutomator可能是异常的不起眼,可是却是有自身独当一面的能力,可以完成许多高难度作业,完...

2.1K1
来自专栏L宝宝聊IT

kvm命令行安装

4422
来自专栏LeoXu的博客

[翻译]Ext JS 教程-MVC架构 原

大规模的客户端应用程序常常难于去编写、组织机构和维护。随着你加入更多的功能,并且投入更多的开发人员,它们渐渐趋向于失去控制。ExtJS 4 带来了一种新的不仅...

851

扫码关注云+社区