• JWT 简介


    以JWT 代替传统Token

    JSON Web Token (JWT)是由Auth0所提构出的一个新Token想法,这并不是一套软件、也不是一个技术,如果你在做网站时有用Token验证使用者身份的习惯,那么这个方法你应该很快就能上手。我们先来讲一讲为什么JWT会比传统Token要好。

    在传统网站中我们会以Session 来判定使用者是否有登入,由于Session 只会被服务端知道,所以我们就可以Session 中存放一些重要数据并且供之后验证用。

    为什么不用Session了?

    随着网络的扩展,Session 有个问题,那就是具状态性(Stateful)还有容易受跨网域请求伪造攻击(CSRF Attack)。 先让我们先以具状态性的问题为例。

    极具状态性

    假设今天有两台服务器通过负载均衡来分派使用者的请求,由于Session是储存在服务端上的,第一次使用者登入时是由Server 1处理,那么这个Session自然也就储存在Server 1 。

    但下次负载平衡指派使用者到Server 2 的时候呢? 这个Session也就不存在 ,所以使用者就需要重新登入一次(虽然有办法可解决,但暂不讨论)。

    易受跨站请求伪造攻击

    由于Session是储存在服务端的,这意味着客户端在发送请求时几乎不用提供什么数据,对吧? 如果今天有人发送了一个删除文章的链接给你,然后你在不知情的情况下就按下去的时候会发生什么事情? 你的文章会这样被删除掉。

    为此,有人想出了Token 来解决这个问题,并且能够在多个服务器上跨域使用。

    Token解决了什么?

    当使用者登入成功时,他会得到一串看起来毫无意义的乱数字串,但这个字串实际上会对应到数据库中使用者的身份,简单说就是另类的帐号,这也被叫做Token。

    无状态性

    Token本身是不携带数据的且无状态性的(Stateless),当服务器接收到Token时,会主动去数据库中找到使用者的数据表,接着就能够知道这个Token代表着哪个使用者,然后获取相关的数据来使用。

    由于多个服务器都是共享一个数据库的,所以我们的服务器现在不会有Session 那样的问题。 但需要注意的是Token 不可以让别人知道,否则别人就能够拥有你的身份、伪造成你。

    安全性提高

    由于使用者现在必须主动提供 Token,也顺带解决了跨网域请求伪造攻击,如果今天朋友再次给了你删除文章的链接,由于这个链接并不带有 Token,服务器也就不能知道是谁想要删除文章,所以这个动作自然就会变成无效。

    为什么要用JWT 取代传统Token?

    你能够直接在JWT 中存放数据,而不用额外的查询数据库。

    当我们使用传统Token时,我们需要查询数据库并且比对这一个Token是谁的,然后我们才能够取得该使用者的数据。 当有大量使用者涌入时,这可能会让服务器负荷不堪。

    而JWT解决了这个问题,因为我们可以直接把使用者数据存放在「Token」中,所以也就省去了额外的数据库开销。 且在微服务架构中也能够方便地获取使用者数据。

    到这里你可能会开始想:「 这样不是很危险吗? 」、「 如果使用者自行修改了Token该怎么办? 」,而我们接下来就要讲一下什么是JWT。

    什么是JSON Web Token(JWT)?

    先看看JWT 的长相吧。

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ 

    上面是一个来自官方网站范例 ,我们将以此做为讲解。

    JWT 的构成

    JWT 实际上是由三个部分组成的。

    标头.内容.签名

    标头

     JWT的标头包含了两个部分,一个是加密类型( alg ),另一个则是定义类型( typ )。

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

    而这些内容通过Base64转化就能够得到我们的第一段字串。

     eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 

    内容

    内容是一个自定义的地方,你可以在里面存放使用者的帐号、昵称,这样你就不需要再去数据库查询,这听起来很不安全,但是不用担心。

    不过需要注意的是这些数据并没有被「加密」,使用者可以直接看到这些数据,所以不推荐在这里摆放信用卡信息、密码。

     { "sub": "1234567890", "name": "John Doe", "admin": true } 

    这部分通过Base64转化也就能得到以下字串。

     eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 

    签名

    这就是好玩的地方了,当我们要签发一个JWT 的时候,我们会用一组密码来签名,这就是为了避免有人自己更改内容,然后拼凑一个根本不是我们所产生的JWT 来欺瞒服务端。

    这部分的算法是由上方两个区块的Base64以点( . )符号组合起来,并以一个字符串(在这里是secret )加密。

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

    然后我们就会得到签名。

     TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ 

    接着组合起来就是JWT 本体。

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ 

    由于secret这个字符串是储存在服务端的,所以也就没有人能够知道(除非暴力破解)。 任何人都可以修改JWT 的内容,但是当他签发的时候并不知道这个字符串,所以就会有不对的签名,服务端也就自然不会接受这个错误的JWT。

    使用JWT 不仅能够节省服务端的数据库连接开销,又能够在数据分享上变得更加便利。

  • 相关阅读:
    vue 如何点击按钮返回上一页
    vue遍历数组和对象的方法以及他们之间的区别
    css隐藏滚动条
    DOM编程以及domReady加载的几种方式
    修改默认滚动条默认样式
    面试题集锦
    正则表达式
    闭包及应用以及顺序处理ajax请求
    实现自己的(模仿jquery)toggle函数
    Asp.Net与SEO Viewstate优化终极解决方案
  • 原文地址:https://www.cnblogs.com/peng104/p/10621821.html
Copyright © 2020-2023  润新知