JSON Web Token 是什么?----->(浅谈)-LMLPHP

 1、JSON Web Token是什么?

JSON Web Token(缩写:JWT),是一套开放的标准(RFC 7519),是目前最流行的跨域身份验证解决方案, 它定义了一种紧凑且自URL安全的方式,以JSON对象的方式在各方之间安全地进行信息传输。由于此信息是经过数字签名的,因此是可以被验证和信任的。可以使用密钥(secret)(使用HMAC算法)或者使用RSA或ECDSA的公有/私有密钥对JWT进行签名。

2. 什么时候应该用JSON Web Token?

下列场景中使用JSON Web Token是很有用的:

  • Authorization (授权) : 这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
  • 跨域身份验证:

        Internet服务无法与用户身份验证分开。一般过程如下:

       1.用户向服务器发送用户名和密码。

       2.验证服务器后,相关数据(如用户角色,登录时间等)将保存在当前会话中。

       3.服务器向用户返回session_id,session信息都会写入到用户的Cookie。

       4.用户的每个后续请求都将通过在Cookie中取出session_id传给服务器。

       5.服务器收到session_id并对比之前保存的数据,确认用户的身份

JSON Web Token 是什么?----->(浅谈)-LMLPHP

          这种模式最大的问题是,没有分布式架构,无法支持横向扩展。如果使用一个服务器,该模式完全没有问题。但是,如果它是服务器群集或面向服务的跨域体系结构的话,则需要一个统一的session数据库来保存会话数据实现共享,这样负载均衡下的每个服务器才可以正确的验证用户身份。

          举一个实际中常见的单点登陆的需求:站点A和站点B提供同一公司的相关服务。现在要求用户只需要登录其中一个网站,然后它就会自动登录到另一个网站。怎么做?

     解决方案:

       一种解决方案是持久化session数据,写入数据库或文件持久层等 ,但是会有单点风险,如果持久层失败,整个认证体系都会挂掉。

        另一种更灵活的解决方案:就是通过客户端保存数据,而服务器根本不保存会话数据,每个请求都被发送回服务器。 JWT是这种解决方案的代表。

JSON Web Token 是什么?----->(浅谈)-LMLPHP

  • Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web Token无疑是一种很好的方式。因为JWT可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用Header和Payload计算的,您还可以验证内容没有被篡改。

3、JSON Web Token的结构是什么样的?

JSON Web Token 是什么?----->(浅谈)-LMLPHP

JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分 分别是:

  • Header : JWT头
  • Payload :  有效载荷
  • Signature : 签名

JSON Web Token 是什么?----->(浅谈)-LMLPHP

接下来,具体看一下每一部分:

3.1、Header(JWT头)

header典型的由两部分组成:token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)。

JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。

JSON Web Token 是什么?----->(浅谈)-LMLPHP

然后,使用Base64 URL算法将上述JSON对象转换为字符串保存就得到JWT的第一部分

3.2、Payload(有效载荷)

JWT的第二部分是payload,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据,它包含声明(要求)。声明是关于实体(通常是用户)和其他数据的声明。声明有三种类型: registered, public 和 private。

  • Registered claims : 这里有一组预定义的声明,它们不是强制的,但是推荐。 JWT指定七个默认字段供选择:

iss:发行人

exp:到期时间

sub:主题

aud:用户

nbf:在此之前不可用

iat:发布时间

jti:JWT ID用于标识该JWT

  • Public claims : 可以随意定义。
  • Private claims : 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。

除以上默认字段外,我们还可以自定义私有字段,如下例:

JSON Web Token 是什么?----->(浅谈)-LMLPHP

请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。

对payload中JSON对象也使用Base64 URL算法转换为字符串保存就得到JWT的第二部分

3.3、Signature(签名哈希)

签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。

首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。

例如:

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."分隔,就构成了整个JWT对象。

签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。

看一张官网的图就明白了:

JSON Web Token 是什么?----->(浅谈)-LMLPHP

3.4、 Base64URL算法

如前所述,JWT头和有效载荷序列化的算法都用到了Base64URL。该算法和常见Base64算法类似,稍有差别。

作为令牌的JWT可以放在URL中(例如api.example/?token=xxx)。 Base64中用的三个字符是"+","/"和"=",由于在URL中有特殊含义,因此Base64URL中对他们做了替换:"="去掉,"+"用"-"替换,"/"用"_"替换,这就是Base64URL算法

4、JSON Web Token是如何工作的?

客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。

此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。

Authorization: Bearer <token>

当跨域时,也可以将JWT被放置于POST请求的数据主体中。

5、 用Token的好处

  • 无状态和可扩展性:Token存储在客户端。完全无状态,可扩展。我们的负载均衡器可以将用户传递到任意服务器,因为在任何地方都没有状态或会话信息。
  • 安全:Token不是Cookie。每次请求的时候Token都会被发送。而且,由于没有Cookie被发送,还有助于防止CSRF攻击。即使在你的实现中将token存储到客户端的Cookie中,这个Cookie也只是一种存储机制,而非身份认证机制。没有基于会话的信息可以操作,因为我们没有会话!
  • 还有一点,token在一段时间以后会过期,这个时候用户需要重新登录。这有助于我们保持安全。还有一个概念叫token撤销,它允许我们根据相同的授权许可使特定的token甚至一组token无效。

6、JWT的问题和优势

1、JWT默认不加密,但可以加密。生成原始令牌后,可以使用改令牌再次对其进行加密。

2、当JWT未加密方法时,一些私密数据无法通过JWT传输。

3、JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。

4、JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。

5、JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。

6、为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。

7. JWT是用在前后端分离, 需要简单的对后台API进行保护时使用

09-02 12:19