zoukankan      html  css  js  c++  java
  • 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协议进行传输。

  • 相关阅读:
    POJ 1811 Prime Test(Miller-Rabin & Pollard-rho素数测试)
    HDU 3037 Saving Beans(Lucas定理模板题)
    HDU 5029 Relief grain(离线+线段树+启发式合并)(2014 ACM/ICPC Asia Regional Guangzhou Online)
    Java进阶(二)当我们说线程安全时,到底在说什么
    UML建模一般流程
    Spring事务管理(详解+实例)
    Spring 的 BeanPostProcessor接口实现
    Spring中ApplicationContext和beanfactory区别
    使用Maven Release插件发布项目
    tair与redis比较总结
  • 原文地址:https://www.cnblogs.com/wwcom123/p/11701498.html
Copyright © 2011-2022 走看看