• 浅谈JWT(Json Web Token)


    一、什么是JWT(Json Web Token)?

    JWT,在HTTP通信过程中,进行身份认证。它是一种开放标准,一种规范化之后的 JSON 结构的 Token。JWT 自身包含了身份验证所需要的所有信息,因此我们的服务器不需要存储 Session 信息。增加了系统的可用性和伸缩性,大大减轻了服务端的压力。

    对比Session和JWT实现认证授权

    首先我们要知道什么是授权。授权就是获得一定的权限后,才能进行某些操作。

    假设我们现在在逛某宝,然后想要查看自己的购物车,那么这时候服务器肯定会对我们进行判断,只有我们登录了才能查看自己的购物车。这个登录的过程就可以理解为对我们进行授权的过程。

    先看看如何通过Session进行授权的:

    • 客户端通过用户名和密码进行登录
    • 服务器验证身份后,生成一个Sessionid存在Cookie中,将对应的Session保存在内存
    • 客户端访问购物车(携带Sessionid)
    • 服务器从Cookie中取出Sessionid,查找对应的Session
    • 如果能够找到对应的Session,则该用户已登录,可以访问购物车,反之不行

    再看看JWT是如何进行授权的:

    • 客户端通过用户名和密码进行登录
    • 服务器验证身份后,生成一个Token保存在Cookie中返回给客户端
    • 客户端访问购物车(客户端每次请求都会携带Token
    • 服务器取出Token进行验证
    • 如果验证成功,则该用户已登录,可以访问购物车

    对比之下我们可以发现,JWT是不用在服务器保存用户的登录信息(Session)的,只用对Token进行验证, 验证成功后返回客户端希望得到的数据就可以了。

    二、JWT组成部分

    JWT是一个很长的字符串,中间用点(.)分隔成三个部分,分别是Header(头部)、Payload(负载)、Signature(签名)。JWT内部是没有换行的,并且都使用Base64编码。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0p21K0ab-1661850662370)(E:/Blog/lansg/source/img/image-20220830151500002.png)]

    1.Header

    Header部分是一个JSON对象,描述JWT最基本的信息,例如Token类型及签名所用的算法等。表示如下:

    {
    	"alg": "HS256",
    	"typ": "JWT"
    }
    
    • 1
    • 2
    • 3
    • 4

    alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);

    typ属性表示这个令牌(token)的类型(type),JWT令牌统一写为JWT。

    最后,将上面的JSON对象使用Base64URL算法转成字符串。

    2.Payload

    Payload部分也是一个JSON对象也是使用Base64URL算法转成的字符串,用来存放实际需要传递的数据。JWT规定了7个官方字段,供选用。

    • iss (issuer) :该JWT的签发者

    • exp (expiration time):过期时间(为一个UNIX时间戳)

    • sub (subject):该JWT所面向的用户

    • aud (audience):接受该JWT的一方

    • nbf (Not Before) :生效时间

    • iat (Issued At) :签发时间

    • jti (JWT ID) :编号

    {
        "iss": "John Wu JWT",
        "iat": 1441593502,
        "exp": 1441594722,
        "aud": "www.example.com",
        "sub": "jrocket@example.com",
        "from_user": "B",
        "target_user": "A"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Payload 部分默认是不加密的,一定不要将隐私信息存放在 Payload 当中!

    3.Signature

    Signature 部分是对前两部分的签名,作用是防止 JWT(主要是 payload) 被篡改。

    这个签名的生成需要用到:

    • Header + Payload
    • secret:存放在服务端的密钥
    • 签名算法

    签名计算公式如下:

    HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5

    算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,这个字符串就是 JWT 。

    JWT是如何进行校验的

    服务端拿到 JWT 之后,会解析出其中包含的 Header、Payload 以及 Signature 。服务端会根据 Header、Payload、密钥再次生成一个 Signature。拿新生成的 Signature 和 JWT 中的 Signature 作对比,如果一样就说明 Header 和 Payload 没有被修改。

    所以密钥是很重要的,密钥决定了签名签名决定了JWT的安全性

    三、JWT的特点

    (1)JWT默认是不加密,但也是可以加密的。生成原始Token以后,可以用密钥再加密一次。

    (2)JWT不加密的情况下,不能将重要数据写入JWT。

    (3)JWT不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

    (4)JWT的最大缺点是,由于服务器不保存session状态,因此无法在使用过程中废止某个token,或者更改token的权限。也就是说,一旦JWT签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

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

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

    (7)便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的

    (8)它不需要在服务端保存会话信息,所以它易于应用的扩展

    四、JWT应用

    • 实现单点登录
    • 解决CSRF问题

    1.单点登录

    在有多个系统的情况下,我们在A系统登录了,如何让B系统也感知到我们已经登录?

    通过JWT的Token,用户访问不同的系统时,只需要从Cookie中取出Token,将Token进行验证一下就可以了。

    不过这样还有一个问题,Cookie是不能跨域的

    比如说,我们请求时,浏览器会自动把google.com的Cookie带过去给google的服务器,而不会把的Cookie带过去给google的服务器。

    这就意味着,由于域名不同,用户向系统A登录后,系统A返回给浏览器的Cookie,用户再请求系统B的时候不会将系统A的Cookie带过去。

    关于跨域问题

    跨域的根本原因就是因为浏览器的同源策略,这是浏览器出于安全性考虑做出的限制,所谓同源是指:域名协议端口相同。

    比如在互联网上有两个资源(网页或者请求等),如果A想要访问B的资源,如果A、B并非同源,即域名、协议、端口有任意一个不相同,那么就会出现跨域问题。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CmrGZNcE-1661850662371)(E:/Blog/lansg/source/img/image-20220830162300092.png)]

    为了解决Cookie的跨域问题,我们可以采取以下几种方法:

    • 服务端将Cookie写到客户端后,客户端对Cookie进行解析,将Token解析出来,请求时将Token放到Http报文的Header部分
    • 多个域名共享Cookie,在写到客户端的时候设置Cookie的domain
    • 将Token保存在SessionStroage中(不依赖Cookie就没有跨域的问题了)

    例如:www.taobao.com、nv.taobao.com、nz.taobao.com、login.taobao.com

    Set-Cookie: jwt=lll.zzz.xxx; HttpOnly; max-age=980000; domain=.taobao.com

    注意domain必须设置为一个点加顶级域名,即.taobao.com。这样,taobao.com和*.taobao.com就都可以接受到这个Cookie,并获取JWT了。

    2.解决CSRF问题

    CSRF,也叫跨站请求伪造,攻击者通过盗用你的身份,以你的名义发送恶意请求。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rft7xg9V-1661850662372)(E:/Blog/lansg/source/img/image-20220830163558670.png)]

    JWT是如何防止CSRF呢?

    CSRF是依靠盗用用户的Cookie来得到用户身份,实现发送请求。为了防止Cookie被盗用,我们可以将JWT的Token存放在SessionStorage或者LocalStorage中,发送请求时将Token放在请求头中。这样不依赖Cookie,自然也就无法进行CSRF攻击了。

    web本地存储SessionStorage和LocalStorage

    • sessionStorage仅在当前会话下有效,关闭页面或浏览器后被清除。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。
    • localStorage生命周期是永久,这意味着除非用户显示在浏览器提供的UI上清除localStorage信息,否则这些信息将永远存在。
  • 相关阅读:
    pytorch lightning最简上手
    【数学建模】——力学模型建立的基本理论及方法
    yolov6训练完模型如何得到每个类别的ap值
    Java ~ JVM ~ Safe Point
    Spring框架面试题总结(面试必备)
    Vue3.0 vue.js.devtools无法显示Pinia调试工具
    SpringCloud之Hystrix
    网络安全—自学笔记
    什么是混淆矩阵精度、召回率、准确性、F1 分数、FPR、FNR、TPR、TNR?
    Taurus.MVC WebAPI 入门开发教程8:WebAPI文档与自动化测试。
  • 原文地址:https://blog.csdn.net/lans_g/article/details/126608442