JWT总结

JWT

  1. 官方文档:https://jwt.io/introduction

  2. 简介:JWT是一种开放标准(RFC 7519) ,它定义了一种紧凑和自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。可以验证和信任此信息,因为它是数字签名的。JWT签名(Signature)可以使用 secret (使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

  3. JWT结构:三大部分字符串,header和payload串是Json对象通过Base64 URL算法加密生成,字符之间通过"."分隔符分为三个子串,所以JWT的有效格式为:Header.Payload.Signature

    JWT总结_第1张图片

    1. Header(头部)

      1. 通常由两部分组成: 令牌的类型(即 JWT)和所使用的签名算法(如 HMAC SHA256或 RSA)。如:

        {
          "alg": "HS256",
          "typ": "JWT"
        }
        
    2. Payload(有效负载)

      1. JWT的主体内容部分,它包含三部分声明(要求)。声明是关于实体(通常是用户)和其他数据的声明,本质上保存有用户数据(如userID)
        1. 标准中注册的声明
          1. JWT 规定了7个官方字段,供选用,建议但不强制使用,详细见官方文档
        2. 公共的声明
          1. 公共的声明可以添加任何的信息,可以随意定义。一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.(一般不定义该声明)
            • 为了避免冲突,它们应该在 IANA JSON Web Token Registry 中定义,或者定义为包含抗冲突名称空间的 URI
        3. 私有的声明
          1. 私有声明是提供者和消费者所共同定义的共享信息声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。
    3. Signature(签名)

      1. 这个签名信息由三部分组成:

        • header (base64后的)
        • payload (base64后的)
        • secret

        这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分

    • 注意:
      • secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
      • JWT真正目的不在加密保护数据,而是为了认证来源,认证来源,认证来源。JWT不保证数据不泄露,因为JWT的设计目的就不是数据加密和保护。
  4. Base64URL

    1. 这个算法跟 Base64 算法基本类似,但有一些小的不同。

      JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+/=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-/替换成_ 。这就是 Base64URL 算法。

  5. JWT用途

    1. 信息存储交换,用于认证来源

      1. 使用 JWT,可以降低服务器查询数据库的次数
      2. 使用JWT,可以降低服务器请求其他其他三方服务器的次数
    2. 身份认证授权

      1. 认证原理

        JWT总结_第2张图片

        这个图中有三个主体: user, application server和authentication server

        非常常见的一个架构:

        1. 首先用户需要 通过登录等手段向authentication server发送一个认证请求,authentication会返回给用户一个JWT,将其存储在Cookie或localStorage中。

        2. 此后用户向application server发送的所有请求都要捎带上这个JWT,然后application server会验证这个JWT的合法性,验证通过则说明用户请求时来自合法守信的客户端。

          • 通用流程:浏览器第一次访问服务器,根据传过来的唯一标识userId,服务端会通过一些算法,如常用的HMAC-SHA256算法,然后加一个密钥,生成一个token,然后通过BASE64编码一下之后将这个token发送给客户端;客户端将token保存起来,下次请求时,带着token,服务器收到请求后,然后会用相同的算法和密钥去验证token,如果通过,执行业务操作,不通过,返回不通过信息。

          • 如何捎带:

            1. 把它放在 Cookie 里面自动发送,但是这样不能跨域

            2. 放在 HTTP 请求的头信息Authorization字段里面:Authorization: Bearer

              //前端api举例
              fetch('api/user/1', {
                headers: {
                  'Authorization': 'Bearer ' + token
                }
              })
              
              • 该方法流程:

                JWT总结_第3张图片

            3. 跨域的时候,JWT 就放在 POST 请求的数据体里面

      2. 可实现场景

        1. 跨域身份验证

          1. 跨域问题:

            互联网服务离不开用户认证。一般流程是下面这样。

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

            2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。

            3、服务器向用户返回一个 session_id,写入用户的 Cookie。

            4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。

            5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

            这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。

            举例来说,A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?

          2. 三类解决方法

            1. 使用Nginx中的ip绑定策略,同一个ip只能在指定的同一个机器访问(不支持负载均衡)

            2. session管理:

              1. session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。

                1. 使用数据库同步session(效率不高)
                2. 使用Spring-Session+Redis实现(保留session最常用的方案)
                  • 以下为两者结合示意图

                JWT总结_第4张图片

              2. session复制同步:使用tomcat内置的session同步(同步可能会产生延迟)

            3. 服务器索性不保存 session 数据了,所需数据都保存在客户端,每次请求都发回服务器。

              1. 使用cookie来完成,cookie保存原session序列化加密信息(很明显这种不安全的操作并不可靠)
              2. 使用token代替session,JWT 就是这种方案的一个代表,以下为示意图。

              JWT总结_第5张图片

            • 三类具体说明或实现见下方什么是session及跨域session解决指定的链接
          3. 与session登录区别

            1. 什么是session及跨域session解决:https://www.cnblogs.com/jing99/p/11785070.html
              • 着重查看session最常用的解决和应用:Spring-session及Redis存储
              • 里面涉及token请忽略,查看下方什么是Token更详细介绍
            2. 什么是Token:https://www.cnblogs.com/lightzone/p/9749076.html,(Json Web Token长什么样子呢?后就无需查看,上文已经介绍过,着重查看优点)
            3. session和token区别:
              1. https://blog.csdn.net/mydistance/article/details/84545768
              2. https://zhuanlan.zhihu.com/p/86937325
                1. 着重查看5.2-5.4
        2. 单点登录

          1. https://www.jianshu.com/p/613e44d4a464
          2. 上述四种方式中,第一种方式:以Cookie作为凭证媒介包括了常用的OAuth2JWT实现
          3. 第四种:使用独立登录系统:其用户中心验证通常都是采用第一种方式进行验证
      3. OAuth2和JWT的区别

        1. oauth2有client和scope的概念,jwt没有。如果只是拿来用于颁布token的话,二者没区别。常用的bearer算法oauth、jwt都可以用。应用场景不同而已
        2. Spring Cloud 的权限框架就是用的jwt实现的oauth2 。二者没有必然联系
        3. Token功能不一样,JWT的token是包含用户基本信息的,然后通过加密的方式生成的字符串,服务器端拿到这个token之后不需要再去查询用户基本信息,解析完token之后就能拿到。想想在微服务架构下,用户服务是一个单独的服务,但是其他服务大部分情况下也会需要用户信息,难道要每次用到都去取一次吗? JWT非常适合微服务。
        4. OAuth2用在使用第三方账号登录的情况(比如使用weibo, qq, github登录某个app)。OAuth2是一个相对复杂的协议, 有4种授权模式, 其中的access code模式在实现时可以使用jwt才生成code, 也可以不用. 它们之间没有必然的联系.
        5. JWT是用在前后端分离, 需要简单的对后台API进行保护时使用.(前后端分离无session, 频繁传用户密码不安全)
        6. JWT是一种认证协议 。JWT提供了一种用于**发布接入令牌(Access Token),**并对发布的签名接入令牌进行验证的方法。 令牌(Token)本身包含了一系列声明,应用程序可以根据这些声明限制用户对资源的访问。
        7. OAuth2是一种授权框架。提供了一套详细的授权机制(指导)。用户或应用可以通过公开的或私有的设置,授权第三方应用访问特定资源。
        • 总结:
          1. Oauth2和jwt是完全不同的两种东西,一个是授权认证的框架,另一种则是认证验证的方式方法(轻量级概念)。
          2. OAuth2不像JWT一样是一个严格的标准协议,因此在实施过程中更容易出错。尽管有很多现有的库,但是每个库的成熟度也不尽相同,同样很容易引入各种错误。在常用的库中也很容易发现一些安全漏洞。
          3. OAuth2常用在使用第三方账号登录的情况(比如使用weibo, qq, github登录某个app),而JWT是常用在前后端分离, 需要简单的对后台API进行保护时使用
      4. JWT缺点

        1. JWT 默认是不加密,故JWT 不加密的情况下,不能将秘密数据写入 JWT。
          1. 解决:可再加密:生成原始 Token 以后,可以用密钥再加密一次。
        2. JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。(再其他博客有查看到一个token撤销概念:它允许我们根据相同的授权许可使特定的token甚至一组token无效。在这里就存在冲突)
      5. JWT安全保证

        1. 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

        2. JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

          1. 请求时token过期自动刷新token?

            当token失效时,现在的网站一般会做两种处理方法:

            1. 跳转到登陆页面,让用户重新登陆获取新的token(OAuth中不包含Refer-Token的方式)
            2. 当检测到请求失效时,网站自动去请求新的token(OAuth中使用Refer-Token的方式去请求,在app保持登陆状态上面用得比较多)

你可能感兴趣的:(支付业务,登录业务,工作必修,java,web,jwt,session,token)