JWT--Json Web Token

【JWT定义

  JSON Web Token(JWT)是一个开放的工业标准RFC 7519,是一个非常轻巧的规范。 

【JWT用途】 

  这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息,在HTTP通信过程中,进行身份认证。

【为什么要身份认证】 

  HTTP通信是无状态的,如果不需要识别用户的浏览,客户端的请求到了服务端处理完之后就结束了。

  但更多时候,是需要识别登录用户的,例如用户登录后浏览、购物车、下单、付款等一系列行为;

  即使不登录的游客,系统也可能标记,需要对访问的客户端进行识别。 

【常用身份认证方式:Session】 

  • 客户端在服务端登录成功之后,服务端会生成一个sessionID,缓存该session(会话),然后响应携带sessionID返回给客户端,客户端将sessionID保存到cookie中。
  • 客户端再次发起请求的时候,携带cookie中的sessionID到服务端,服务端解析获取sessionID并与自身缓存匹配,就知道是哪个用户的请求。

    常用的session解决方案,会遇到以下问题:      

  • session保存在服务端,当客户访问量增加时,服务端就需要存储大量的session会话,对服务器有很大的考验;      
  • 当服务端为集群时,用户登录其中一台服务器,会将session保存到该服务器的内存中,但是当用户的访问到其他服务器时,会无法访问。这个通常可以采用第三方分布式缓存等技术共享保存session,来解决该问题。 

【另一种身份认证方式:JWT】

  • 客户端通过用户名和密码登录服务器;
  • 服务端对客户端身份进行验证;
  • 服务端对该用户生成Token,返回给客户端;
  • 客户端发起请求,需要携带该Token;
  • 服务端收到请求后,首先验证Token,之后返回数据。
  • 客户端将Token保存到本地浏览器,一般保存到cookie中。

   与Session方案的区别是:

    服务端不需要保存Token,只需要对Token中携带的信息进行验证即可;

    无论客户端访问后台的那台服务器,只要可以通过用户信息的验证即可。

    JWT 的原理是,

    服务器认证以后,生成一个 JSON 对象,发回给用户,

    例如:{ "姓名": "张三", "角色": "管理员", "到期时间": "2018年10月31日0点0分"}

  以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。

  为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名signature(详见后文)。

  这样服务器就可以不保存任何 session 数据了,也就是说,服务器变成无状态了,从而更容易实现扩展。

  也可以理解session是消耗服务器内存存储的方式,JWT是消耗服务器CPU计算的方式。 

【JWT组成】

  JWT由3段信息组成:

  • header信息
  • payload信息
  • signature信息

  这3段信息分别base64URL编码后,用英文句号.分隔连在一起,组成JWT字符串。 

    

   header

  header承担两部分信息:

  • 声明令牌类型typ:固定填写JWT。
  • 声明signature使用的加密算法alg:默认使用HMAC-SHA256(写为HS256)。

{
  'typ': 'JWT',
  'alg': 'HS256'
}

  然后将header进行base64URL加密,组成JWT的第1段。 

     payload

  payload是JWT存放有效信息的地方,包含3部分:

  • 标准中注册声明 (建议但不强制使用) 

    iss: JWT的签发者

    sub: 服务订阅者,也就是发起请求的服务消费者

    aud: 服务提供者,也就是接收请求,验证通过后才提供服务

    iat: JWT的签发时间

    exp: JWT的过期时间,这个过期时间必须要大于签发时间

    nbf: 定义在什么时间之前,该JWT都是不可用的

    jti: JWT的唯一标识,唯一性标识token,防重放攻击

  • 公共声明

    可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。

  • 私有声明

    服务提供者和服务消费者共同定义的声明。  

  然后将payload进行base64URL编码,组成JWT的第2段。  

  注:payload务必不要存放敏感信息,因为base64URL只是一种编码方式,payload信息本身并不加密。 

     signature

  JWT的第3段signature是签名信息,用于保证JWT的payload信息的完整性(header和payload数据不会被篡改)。

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

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

  客户端收到服务端消息后,解析出header和payload,再按同样算法,使用公钥验签。验签通过,证明这是服务端发来的消息,是完整的。

【Base64URL编码】   

   编码的原因:方便以字节的方式表示数据,便于存储和网络传输。 

  如前所述,JWT的header和payload都用到了Base64URL编码。该编码方式和常见Base64算法类似,稍有差别。 

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

【用法】 

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

  此后,客户端将在与服务器交互中都会带JWT。

  如果将它存储在Cookie中,就可以自动发送,但是不能跨域,

  因此一般是将JWT放入HTTP请求的Header头信息 Authorization字段中   Authorization: Bearer 

  另一种做法是,当跨域时,将JWT被放置于POST请求的数据主体中。 

【注意】 

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

  2、当JWT未加密时,一些私密数据千万不要通过JWT传输。 

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

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

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

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

 

posted @ 2019-10-21 00:02  wwcom123  阅读(354)  评论(0编辑  收藏  举报