百家饭平台是我们团队研发的,OpenAPI的编辑、测试、代码生成的工具,我们将围绕OpenAPI做一系列的介绍文章。如果没有特殊声明,介绍的OpenAPI标准以v3.1.0版本为主。

  1. API的认知方法
  2. 浅谈JWT认知

上周介绍了API认证方法在OpenAPI标准中的定义,其中提到JWT认证是Bearer认证的一种,主要表现形式是在头部的Authorization字段加入Bearer ....的加密内容构建一个Token认证的基本架构。因为我们的客户要求支持JWT认证,因此我们对此做了一些深入的研究工作。

什么是JWT认证?

JSON Web Token (JWT) is a compact, URL-safe means of representing
   claims to be transferred between two parties.  The claims in a JWT
   are encoded as a JSON object that is used as the payload of a JSON
   Web Signature (JWS) structure or as the plaintext of a JSON Web
   Encryption (JWE) structure, enabling the claims to be digitally
   signed or integrity protected with a Message Authentication Code
   (MAC) and/or encrypted.

JSON Web Token (JWT)是一种用于机构之间的、紧凑的、URL安全的表征身份申明的方法。JWT中的身份申明信息被编码为JSON对象,通过和消息鉴权码(MAC)和加密手段一起使用,在基于JSON的Web签名“(JSON Web Signature-JWS)中(作为签名内容)和在”基于JSON的Web加密“(JSON Web Encryption - JWE)中(作为加密明文),用于数字签名或完整性保护.

上面这段英文摘自RFC 7519: JSON Web Token (JWT) ,下面这段来自我的翻译,英文写的有点绕,中文也跟着绕了进去,总之JWT是一种JSON编码的认证信息传递方式。我翻阅了一下资料,JWE比JWS多了加密的部分,按目前在HTTP认证中的应用情况,还是JWS为多,所以下面的介绍以JWS为主。

一个JWT例子

下面是一个例子:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.4M4_vn5XBnPYrGQBM4b2nB4Q5HX1PNHUPXI-z250Jj0

仔细的看可以发现,这段代码被.分成了三个部分:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
4M4_vn5XBnPYrGQBM4b2nB4Q5HX1PNHUPXI-z250Jj0

这是JWT放入头部Authorization的内容,是一串base64加密的字符串,解密后为

{"alg":"HS256","typ":"JWT"}
{"sub":"1234567890","name":"John Doe","iat":1516239022}
⹹\ϢΛڰxCהGPȏnt&=

可以看出其实JWT(JWS)是个明文传输内容,第一行(也就是第一个.之前的内容是编码方式介绍,这个例子用到了HS256算法,并表明自己的类型是JWT。第二行是JSON存储的认证内容,官方包含了以下几种保留字段:

iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号

当然,作为JSON对象,扩展或使用其他字段也是随意的事情。

第三行看起来没有字面意义,实际是个校验key,表明使用某个key在指定的HS256算法下,对前两个字段计算所得的签名。

这里推荐一个网站:

JSON Web Tokens - jwt.io 

这个网站有JWT的样例和验算工具,还有推荐的各语言实现包,我们选用了其中推荐的GitHub - SermoDigital/jose: A comprehensive set of JWT, JWS, and JWE libraries.

JWT的用处

从上面的介绍可以看出,我们通过合适的工具构建一个符合要求的JSON对象,计算Token,并全部Base64编码就可以生成一个JWT认证的token,用于用户的鉴权验证。我们想大概的应用逻辑可能有以下几种:

 服务器生成,用于加密接口的后续鉴权

服务器通过自己的密钥,对通过非加密要求的接口(例如登录接口)传递的用户信息进行验证,验证后加密生成JWT Token,传回客户端之后,客户端用于后续加密,由于密钥只有服务器清楚,因此Token的验证是有效的。这种模式等同于session模式,负载中可以加入时间戳,加强有效事件管理,因为密钥只有服务器清楚,因此,在后续的操作中,只要Token有效,即可认为是有效访问。坏处是需要事先登录。

客户端和服务器协商密钥生成,用于所有接口的鉴权

客户端通过事先和服务器协商过的密钥,在任意接口访问时,附加生成的JWT Token,负载中按协商要求,添加有效负载,至少包括身份ID信息。服务器收到请求后,通过身份ID信息,从数据库获取密钥,并通过密钥重新生成Token,进行比对鉴权。这种模式下避免了用户密钥在负载中的传输,是相对于Basic认证而言,更好的认证手段,但是基础逻辑和Auth Key等方式相同,虽然不再需要登录流程,但是因为每次都需要读取用户信息,相对消耗会更大。

客户端通过私钥生成,共享公钥用于鉴权

由于JWT支持RS256及以上的非对称加密算法,因此上述协商逻辑还可以进一步增强成客户端通过自身私钥进行Token的生成,提交服务器,服务器通过公钥进行有效性验证,这时用户的生成私钥就完全的不需要提交给服务器,只需要服务器上实现向用户提供一个上传公钥的入口就好了。有点类似目前各大Git网站提供的公钥上传功能类似。

对JWT的评价

总的来说,我觉得JWT所提供的认证功能,总的来说还是和现有HTTP认证手段不相伯仲,但是通过标准化,加强了手段的通用性,并且由于采用JSON格式,在nodejs等场景有更多的认可度。是个可以尝试的认证手段。推荐选用jwt.io测试过的开源软件包

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐