原文:IdentityServer4实战 - 谈谈 JWT Token 的安全策略

一.前言

众所周知,IdentityServer4 默认支持两种类型的 Token,一种是 Reference Token,一种是 JWT Token 。前者的特点是 Token 的有效与否是由 Token 颁发服务集中化控制的,颁发的时候会持久化 Token,然后每次验证都需要将 Token 传递到颁发服务进行验证,是一种中心化的比较传统的验证方式。JWT Token 的特点与前者相反,每个资源服务不需要每次都要都去颁发服务进行验证 Token 的有效性验证,该 Token 由三部分组成,其中最后一部分包含了一个签名,是在颁发的时候采用非对称加密算法(最新的JWT Token)进行数据签名的,保证了 Token 的不可篡改性,保证了安全,与颁发服务的交互,仅仅是获取公钥用于验证签名,且该公钥获取以后可以自己缓存,持续使用,不用再去交互获得,除非Token包含的 keyid 对应的 公钥没被缓存(新的),就会再次向颁发服务获取。我画了一张流程图,大家可以去查看:https://www.cnblogs.com/stulzq/p/9226059.html

这里说一下我在文章说所说的名词:

颁发服务:即生成Token的服务。

资源服务:提供给用户访问的API资源

二.JWT Token 的安全问题

前言中有过叙述,JWT 类型的 Token 在验证的时候,无需依靠颁发服务来验证 Token 的有效性,是一种去中心化的验证方式,这就意味着颁发服务无法集中控制 Token。假如 Token 暴露以后,在 Token 有效期内,将会一直被人恶意使用,这时候该怎么办呢?这里主要从两个方面来讲,一个是尽量避免被恶意获取Token,一个是被恶意获取了怎么控制失效。请听下面分解。

1.使用 HTTPS

此种方式是避免被人获取恶意获取Token。

HTTPS 在传输数据时,数据内容是加密的,可以有效避免中间人攻击,所以在使用 JWT Token 的程序建议都采用HTTPS。

2.添加自定义Token失效机制

此种方式是被恶意获取了怎么控制失效。

因为 IdentityServer4 对 JWT Token,默认是没有控制失效的机制的,所以如果我们想添加这种机制,只有我们自定义,下一节做详细介绍。

三.自定义Token失效机制

1.简单黑名单模式

顾名思义,就是添加一个 Token 黑名单,这个黑名单建议存在诸如 Redis 等分布式缓存,数据库等介质,可以让所有资源服务共同访问。不推荐添加在资源服务本地缓存,如果这样做,那么每次添加黑名单还需要同步到每个资源服务。每个资源服务在每次验证Token的时候需要查询一下黑名单,如果在黑名单里面,即 Token 无效。

2.进阶黑名单模式

前面小节的 【简单黑名单模式】 有一个非常大的弊端,就是每个 Token 验证时都需要去验证是否在黑名单,正常情况下,我们正常的Token 是占绝大多数的,如果用此种机制,那么对资源是一种很大的浪费。那么我们需要设立一种机制,来让我们认为 可疑 的Token进行黑名单验证,那么如何来判断Token是否可疑呢,我这里想了一种方式。

如何判断 Token 是否可疑:

我们在生成Token的时候,可以添加自定义 Claim (身份信息单元),那么我们可以参考网站登录的安全机制,那么我们可以添加一个用户ip的Claim,这样我们生成的Token都会携带用户生成Token时的IP,我们每次验证Token是否有效时,就可以根据客户端来源IP与Token携带的IP进行匹配,如果匹配不上,那么该Token我们就可以认为是可疑的,从而进行黑名单的验证。

该方式相对于前面的 【简单黑名单模式】模式算是一个比较好的进阶了。

在这里,我们还需要考虑到IP作为用户的私密信息,我们将IP放入Token时,需要对IP进行加密。因为 JWT Token 前两部分,仅仅是 base64 Encode 而已。

Claim 详解请参考 http://www.cnblogs.com/stulzq/p/8726002.html

3.强化黑名单模式

无论是【简单黑名单模式】还是【进阶黑名单模式】,我们在对比黑名单时是对token进行完全比对,这样的方式,在某些场景就存在局限性,比我想让该用户在某某时间以前颁发的Token都算作黑名单。所以我们在判断黑名单时可以根据用户id以及token颁发时间来判断。如果让规则自动失效?我们可以用前面设定的 token颁发时间加上我们颁发服务设置的token有效时间就等于规则失效时间。

4.将Token添加进黑名单的方式

我们前面设立了黑名单模式,那么我们的Token何时加入黑名单呢,难道让用户说,我的 Token 被盗了,你把我的 Token加入黑名单吧,这肯定不现实。我们可以在退出登录时,就自动往黑名单添加一条规则,采用【强化黑名单模式】添加用户id以及当前时间作为token颁发时间来验证。比如用户id1000,此用户在 2018-09-20 12:11 退出,我们就可以添加一条规则 userid=1000,tokenissuetime=2018-09-20 12:11 ,该规则表示只要用户id为1000的并且token颁发时间小于2018-09-20 12:11的token,都被算作黑名单token。

这时有人可能会说,这个token如果还是这个用户再次拿来使用,那还是有效的,你这个怎么没让他失效呢?我们设立黑名单模式就是为了避免用户的还在有效期的Token被他人恶意使用。对于用户自己来说,这个问题就无关紧要了。

5.全部 Token 失效的机制。

全部Token失效的方式,目前我想了两种:

1.更换颁发服务的密钥对,并且重启所有资源服务(资源服务获取的公钥默认存在内存,重启可以丢失)。这样原本的Token在验证时,将会找不到对应的公钥,导致验签失败从而Token无效。

2.类似于前面【强化黑名单模式】的验证黑名单的方式,我们可以在验证Token的流程中加两个配置,一个是控制这种配置是否开启的开关,一个是某个时间,规则就是如果在这个时间以前颁发Token全部算作无效Token。这种就需要资源服务支持热加载配置,从而避免重启资源服务。

我个人推荐第二种方式。

四.其他解决方案

这里的内容是根据评论整理的,我个人的想法不可能面面俱到,所以整理了一下评论里比较不错的方案:

Savorboard:

JWT 的最佳实践是遵循默认的过期策略(15分钟过期), 他能够有效的保证Token的有效性。 刷新Token是为了保证身份验证的服务端与授予令牌的客户端在访问权限方面保持一致,比如Claim里可能包含最新的访问权限,这是一个必要且必须的过程。

所以,频繁的15分钟刷新令牌是有必要的,这并不足以对服务器的性能产生很大的影响。

五.写在最后

文中所诉是总结了我长久以来的想法,token加入ip还有根据id和颁发时间验证黑名单都是我今天无意间想到的。如果你阅读了本文有什么不明白或者你认为有改进的地方,或者更好的地方,欢迎在评论与我交流。本文的问题,有很多人问过我,也讨论了不少,我相信很多人在使用ids4是可能会有这样的问题,所以在此发表了我的一个观点,希望能给你参考,后续的文章我会根据这个想法来实现。

IdentityServer4实战 - 谈谈 JWT Token 的安全策略的更多相关文章

  1. IdentityServer4实战 - 谈谈 JWT 的安全策略

    一.前言 众所周知,IdentityServer4 默认支持两种类型的 Token,一种是 Reference Token,一种是 JWT Token .前者的特点是 Token 的有效与否是由 To ...

  2. 关于 IdentityServer4 中的 Jwt Token 与 Reference Token

    OpenID Connect(Core),OAuth 2.0(RFC 6749),JSON Web Token (JWT)(RFC 7519) 之间有着密不可分联系,对比了不同语言的实现,还是觉得 I ...

  3. IdentityServer4实战 - JWT Token Issuer 详解

    原文:IdentityServer4实战 - JWT Token Issuer 详解 一.前言 本文为系列补坑之作,拖了许久决定先把坑填完. 下文演示所用代码采用的 IdentityServer4 版 ...

  4. ASP.NET Core 实战:基于 Jwt Token 的权限控制全揭露

    一.前言 在涉及到后端项目的开发中,如何实现对于用户权限的管控是需要我们首先考虑的,在实际开发过程中,我们可能会运用一些已经成熟的解决方案帮助我们实现这一功能,而在 Grapefruit.VuCore ...

  5. IdentityServer4实战 - JWT Issuer 详解

    一.前言 本文为系列补坑之作,拖了许久决定先把坑填完. 下文演示所用代码采用的 IdentityServer4 版本为 2.3.0,由于时间推移可能以后的版本会有一些改动,请参考查看,文末附上Demo ...

  6. IdentityServer4实战 - AccessToken 生命周期分析

    一.前言 IdentityServer4实战这个系列主要介绍一些在IdentityServer4(后文称:ids4),在实际使用过程中容易出现的问题,以及使用技巧,不定期更新,谢谢大家关注.使用过id ...

  7. IdentityServer4实战 - 基于角色的权限控制及Claim详解

    一.前言 大家好,许久没有更新博客了,最近从重庆来到了成都,换了个工作环境,前面都比较忙没有什么时间,这次趁着清明假期有时间,又可以分享一些知识给大家.在QQ群里有许多人都问过IdentityServ ...

  8. IdentityServer4 实战文档

    一.前言 IdentityServer4实战这个系列主要介绍一些在IdentityServer4(后文称:ids4),在实际使用过程中容易出现的问题,以及使用技巧,不定期更新,谢谢大家关注.这些问题. ...

  9. Spring Cloud OAuth2.0 微服务中配置 Jwt Token 签名/验证

    关于 Jwt Token 的签名与安全性前面已经做了几篇介绍,在 IdentityServer4 中定义了 Jwt Token 与 Reference Token 两种验证方式(https://www ...

随机推荐

  1. MySQL參数binlog-do-db对binlogs写入的影响

    1. 环境描写叙述 目的:当数据库中设置了binlog-do-db时.在不同的binlog_format=statement | row | mixed 下对binlog的写入影响,这个在主从复制中会 ...

  2. 【LCS】POJ1458Common Subsequence

    题目链接:http://poj.org/problem?id=1458 这是一道最长公共子序列的模板题: #include<iostream> #include<string> ...

  3. 每日技术总结:Better-scroll应用于弹出层内容滚动

    一.Better-scroll在项目中的应用 Better-scroll这款滚动插件还是很好用的,通常不会有什么问题.但偶尔总会出点意外.今天再次使用better-scroll,记录一下这次顺利的过程 ...

  4. 【习题 3-3 UVA-1225】Digit Counting

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 水模拟 [代码] #include <bits/stdc++.h> using namespace std; int a ...

  5. sum()函数——MATLAB

    a=sum(A)  %列求和 b=sum(A,2) %行求和 c=sum(A(:)) %矩阵求和 假定A为一个矩阵: sum(A)以矩阵A的每一列为对象,对一列内的数字求和. sum(A,2)以矩阵A ...

  6. 18.1 IIC驱动程序(基于3.4.2内核)

    驱动使用smbus提供的IIC读写函数可以参考smbus-protocol.txt文档:应用层直接使用IIC读写函数读写IIC设备,应用层读写函数是由i2c-tools这个库提供的(编译的使用和应用程 ...

  7. 【BZOJ 3675】[Apio2014]序列分割

    [链接] 链接 [题意] 在这里输入题意 [题解] 模拟一下样例. 会发现.切的顺序不影响最后的答案. 只要切点确定了. 答案就确定了. 则设f[i][j]表示前i段,第i段保留到j的最大值. \(f ...

  8. Nginx+Tomcat搭建高性能负载均衡集群的实现方法

    一.    目标实现高性能负载均衡的Tomcat集群: 二.步骤 1.首先下载Nginx,要下载稳定版: 2.然后解压两个Tomcat,分别命名为apache-tomcat-6.0.33-1和apac ...

  9. NASM Syntax

    NASM has a simplified syntax designed to let the user code with minimum overhead. In its simplest fo ...

  10. Spring boot(二) springboot + jsp

    官方不推荐JSP在Spring Boot中使用! 一.添加依赖 在pim.xml 里面添加以下 jsp依赖 <dependency> <groupId>org.springfr ...