JTW(Json Web Token)
跨地域认证问题(转载)
任何服务都离不开服务器认证的问题,一般的服务器认证流程如下:
上面显示的是单点验证的情况,如果一个公司有多个服务器,当员工登录上一个服务器,按照正常情况,他就可以免密登录其他的服务器,这是如何实现的?见下图:
上面的中间件层可以简单看做是一个mysql数据库,那么就存在一个问题,如果中间件层挂了,那么所有的单点登录都会失败,另一个方法就是session存在客户端,服务器端不存储session,每次请求都讲session发送给服务器,JTW是这种方案的代表之一。
JTW
1、什么是JTW
Json Web Token是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全的将信息以json的格式传输,由于这些信息都是进过数字签名的,所以它是可以被验证和信任的。可以使用HMAC算法或使用RSA或ECDSA的公用/专用密钥对对JWT进行签名。
2、JTW原理
JTW是在服务器认证之后,生成一个json对象,返回给用户,比如:
{
"name":"liming",
"actor":"admin",
"time":"2020-08-08"
}
之后,用户与服务通信的时候,都要发回这个json对象。服务器完全只靠这个对象去认定身份;当然,为了防止数据篡改,服务器在生成json数据的时候会加上签名。服务器就不保存任何session数据,也就是说,服务器现在就是无状态的了。
3、JTW数据结构
JTW数据结构分为三个部分,用.连接,分别为头部、负载和签名,如下:
header.payload.signature
3.1、header
header是一个json对象,里面一般包括了签名的算法和token的类型,这里也就是JTW,如下:
{
"alg":"HS265",
"typ":"JWT"
}
上面的json格式数据会被Base64URL算法转换成字符串,成为最终的header。
3.2、payload
payload部分也是一个json格式的数据。JWT官方定义了7个字段供选用,如下:
1 iss (issuer):签发人
2 exp (expiration time):过期时间
3 sub (subject):主题
4 aud (audience):受众
5 nbf (Not Before):生效时间
6 iat (Issued At):签发时间
7 jti (JWT ID):编号
当然,你也可以定义自己的私有字段,但是JWT是默认不加密的,所以并不建议把敏感数据放在里面,同样payload也需要用Base64URL算法转换成字符串。举一个栗子:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
3.3、signature
signature是对前两个部分的数据进行签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.
)分隔,就可以返回给用户。
3.4、Base64URL
前面提到,Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。
JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+
、/
和=
,在 URL 里面有特殊含义,所以要被替换掉:=
被省略、+
替换成-
,/
替换成_
。这就是 Base64URL 算法。
4、JWT 的几个特点
(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。
(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。