美文网首页
前端也有必要了解JWT吗?

前端也有必要了解JWT吗?

作者: 码途有道 | 来源:发表于2021-04-02 17:34 被阅读0次

    什么是JWT

    JWT全称是JSON WEB TOKEN,是一种基于JSON的开放标准(RFC 7519),主要用于用户与服务器之间安全地传输信息。简单的说,JWT就是一种认证机制。

    推荐

    文章将率先在公众号「Code满满」与个人博客「李益的小站」上发布,如果本文对你有帮助,就关注一下公众号吧!

    什么是认证

    HTTP协议本身是一种无状态的协议,在应用程序中,用户需要输入用户名和密码来进行用户认证,获取属于用户自己的信息。但是如果每次都要用户输入用户名和密码,就太过于繁琐了;于是就有了Session认证Token认证

    传统的Session认证

    Session是一种记录客户端和服务器端会话状态的机制,是基于Cookie实现的,其认证流程如下:

    1. 客户端第一次请求服务器,服务器根据客户端提交的信息,创建对应的Session
    2. 服务器一般将Session保存在内存中,然后将SessionID返回给客户端
    3. 客户端收到SessionID后,会将SessionID保存在Cookie中,并记录此SessionID属于哪个域名
    4. 客户端第二次请求时,会将此域名下的Cookie信息发送给服务器,服务器获取Cookie信息后,会从中提取出SessionID并去查找自己保存的对应的Session;如果找到,则说明认证成功,否则认证失败

    Session有如下缺陷:

    • 因为Session一般保存在服务器的内存中,随着用户增多,服务器的开销会越来越大
    • 因为Session是存在内存中,会带来一些扩展性问题
    • 因为是基于Cookie来进行用户识别的, Cookie如果被截获,用户就会很容易受到CSRF攻击(跨站请求伪造攻击)

    传统的Token认证

    传统的Token认证流程如下:

    1. 客户端输入用户名和密码来请求服务器,服务器会根据客户端提交的信息,创建一个Token
    2. 服务器会将Token存储在数据库中或者缓存起来,然后将Token返回给客户端
    3. 客户端收到Token后会保存在本地,并在每次请求时带上Token,一般会放在请求的Header中
    4. 服务器会从请求信息中获取Token,并去查库验证Token是否有效

    这种基于Token的认证是无状态的,能有效的防止CSRF攻击,但是这种认证方式不是没有缺陷,比如:每次服务器验证Token是否有效时都要去查库,这也是一种消耗;另外,客户端退出登录时也必须调用接口来通知服务器删除Token,比较繁琐。

    JWT认证

    JWT是目前主流的认证方式,其认证流程如下:

    1. 客户端输入用户名和密码来请求服务器,服务器根据客户端提交的信息,会创建一个Token,并返回给客户端,自己不会保存这个Token
    2. 客户端获取Token后会保存在本地,每次请求时都带上Token,一般会放在请求的Header中
    3. 服务器获取请求信息中的Token后,会直接解析这个Token,从中获取用户的相关信息,不用去查库;如果解析成功,则代表认证成功,否则代表Token无效,认证失败

    JWT认证与传统的Token认证不同的地方在于:JWT认证的Token是交由客户端保管的,服务器端一般不存储Token;服务器验证Token是否有效是通过能否直接解析Token来判断的,如果能解析,则表示有效,否则无效。这样做的好处,就是服务器不用存储Token,不用查库,减少开销;在分布式或者多服务器的应用中,每个服务器都可以直接判断Token是否有效并解析,而不必去单独访问一个专门存储Token的服务器,扩展性得到很大提升。

    从上述内容中可以明显看出,JWT认证的强大之处在于可以从Token中解析出有用的数据,而不像传统的Token,仅仅是一个身份标识。下面我们就看一下,JWT是怎样构成的。

    构成

    JWT共有三部分构成:

    • Header(头部)
    • Payload(负载)
    • Signature(签名 )

    Header(头部)

    头部一般会记录两种信息:

    • 声明Token的类型,一般声明为JWT
    • 声明加密算法名称,一般声明为HMAC、**SHA256 **等

    完整案例如下:

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

    然后将头部信息使用Base64编码,构成Token的第一部分。

    Payload(负载)

    负载是存放有效信息的地方,包含三种声明:Registered claims(注册声明), Public claims(公共声明) 以及Private claims(私有声明)

    • 注册声明:一组预定义的声明,不强制,但推荐

      • iss (issuer):jwt签发者
      • sub (subject):jwt所面向的用户
      • aud (audience):接收jwt的一方
      • iat (issued at):jwt的签发时间
      • exp (expiration):jwt的过期时间,这个过期时间必须要大于签发时间
      • nbf (not before):声明jwt在指定的时间后有效
      • jti (JWT ID):jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击(如果JWT标识存在,那么发出者不能复用同一JWT标识,如果一JWT的jti声明与另一JWT完全相同,则被视为重放攻击)
    • 公共的声明:可以添加任何的信息,一般添加用户的相关信息或其它业务需要的信息,但不建议添加敏感信息

    • 私有的声明:一般是签发者和接收者所共同定义的声明,不建议存放敏感信息

    完整案例如下:

    {
        "iss": "www.liyisite.com"
        "sub": "1234567890",
        "exp": 1618400868
        "user_id": "1",
        "username": "liyi",
    }
    

    对Payload进行Base64编码就得到JWT的第二部分。

    Signature(签名 )

    JWT的第三部分是一个签名信息,它是用Header中指定的那个签名算法对编码过的Header、编码过的Payload以及一个秘钥进行签名,从而生成的。

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

    缺陷

    JWT虽然有种种好处,但是也有缺陷。因为JWT是一经签发,在未到期前都是有效的,加上token是存放在客户端,所以服务器无法废弃token。这意味着如果token被他人获取,即使签发新token,只要旧token未到失效时间,就依然有效,他人依然可以使用,这是非常危险的。

    此时,后端一般会使用Redis等工具来缓存签发的jwt,设立黑名单,当签发新的jwt后,就会把旧jwt放入黑名单,直至旧jwt失效后,从缓存中移除。不过如此一来,就有点违背JWT的原则了。

    相关文章

      网友评论

          本文标题:前端也有必要了解JWT吗?

          本文链接:https://www.haomeiwen.com/subject/tisqkltx.html