Token验证JWT方法

2022年8月7日10:15:55
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
  1. 客户端使用用户名跟密码请求登录
  2. 服务端收到请求,去验证用户名与密码
  3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

JWT验证

JWT,读作:jot ,表示:JSON Web Tokens

JWT 标准的 Token 有三个部分:

  • header(头部)
  • payload(数据)
  • signature(签名)

中间用点分隔开,并且都会使用 Base64 编码,所以真正的 Token 看起来像这样:

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

Header

每个 JWT token 里面都有一个 header,也就是头部数据。里面包含了使用的算法,这个 JWT 是不是带签名的或者加密的。主要就是说明一下怎么处理这个 JWT token 。

唯一在头部里面要包含的是alg 这个属性,如果是加密的 JWT,这个属性的值就是使用的签名或者解密用的算法。如果是未加密的 JWT,这个属性的值要设置成none

eg:

{"alg":"HS256"}

意思是这个 JWT 用的算法是 HS256,在base64url编码之后变成

eyJhbGciOiJIUzI1NiJ9

Payload

Payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也可以添加其它需要的内容。

  • iss:Issuer,发行者
  • sub:Subject,主题
  • aud:Audience,观众
  • exp:Expiration time,过期时间
  • nbf:Not before
  • iat:Issued at,发行时间
  • jti:JWT ID

两个自定义的字段,一个是name ,还有一个是admin

{"iss":"ninghao.net","exp":"1438955445","name":"wanghao","admin":true}

使用 base64url 编码以后就变成了这个样子:

eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ

Signature

JWT 的最后一部分是 Signature ,这部分内容有三个部分,先是用 Base64 编码的header.payload,再用加密算法加密一下,加密的时候要放进去一个 Secret ,这个相当于是一个密码,这个密码秘密地存储在服务端。

组成结构是这样子:

  • header
  • payload
  • secret
const encodedString=base64UrlEncode(header)+"."+base64UrlEncode(payload);HMACSHA256(encodedString,'secret');

处理完成以后看起来像这样:

SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

最后这个在服务端生成并且要发送给客户端的 Token 看起来像这样:(由以上三部分组成)

eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

客户端收到这个 Token 以后把它存储下来,下回向服务端发送请求的时候就带着这个 Token 。服务端收到这个 Token ,然后进行验证,通过以后就会返回给客户端想要的资源。

准备项目

准备一个简单的 Node.js 项目:

C:\Users\bnkj>cd desktopC:\Users\bnkj\Desktop>mkdir jwt-demoC:\Users\bnkj\Desktop>cd jwt-demoC:\Users\bnkj\Desktop\jwt-demo>npm init-y

安装签发与验证 JWT 的功能包,我用的叫jsonwebtoken,在项目里安装一下这个包:

C:\Users\bnkj\Desktop\jwt-demo>npm install jsonwebtoken

签发 JWT

在项目里随便添加一个 .js 文件,比如index.js,在文件里添加下面这些代码:

const jwt=require('jsonwebtoken')// Token 数据const payload={
  name:'wanghao',
  admin:true}// 密钥const secret='ILOVENINGHAO'// 签发 Tokenconst token= jwt.sign(payload, secret,{ expiresIn:'1day'})// 输出签发的 Token
console.log(token)

非常简单,就是用了刚刚为项目安装的jsonwebtoken 里面提供的jwt.sign 功能,去签发一个 token。这个sign方法需要三个参数:

  1. playload:签发的 token 里面要包含的一些数据。
  2. secret:签发 token 用的密钥,在验证 token 的时候同样需要用到这个密钥。
  3. options:一些其它的选项。

在命令行下面,用node 命令,执行一下项目里的index.js 这个文件(node index.js),会输出应用签发的token

C:\Users\bnkj\Desktop\jwt-demo>node index.js
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzM5MDYsImV4cCI6MTUyOTEyMDMwNn0.DctA2QlUCrM6wLWkIO78wBVN0NLpjoIq4T5B_2WJ-PU

上面的 Token 内容并没有加密,所以如果用一些 JWT 解码功能,可以看到 Token 里面包含的内容,内容由三个部分组成,像这样:

// header{"alg":"HS256","typ":"JWT"}// payload{"admin":true,"iat":1529033906,"name":"wanghao","exp":1529120306}// signature
DctA2QlUCrM6wLWkIO78wBVN0NLpjoIq4T5B_2WJ-PU

验证 JWT

打开项目的 index.js 文件,里面添加几行代码,变成下面的样子:

const jwt=require('jsonwebtoken')// Token 数据const payload={
  name:'wanghao',
  admin:true}// 密钥const secret='ILOVENINGHAO'// 签发 Tokenconst token= jwt.sign(payload, secret,{ expiresIn:'1day'})// 输出签发的 Token
console.log(token)// 验证 Token
jwt.verify(token, secret,(error, decoded)=>{if(error){
      console.log(error.message)return}
    console.log(decoded)})

把要验证的 Token 数据,还有签发这个 Token 的时候用的那个密钥告诉 *verify* 这个方法,在一个回调里面有两个参数,*error* 表示错误,*decoded* 是解码之后的 Token 数据。

执行:

C:\Users\bnkj\Desktop\jwt-demo>node index.js

输出:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzQ3MzMsImV4cCI6MTUyOTEyMTEzM30.swXojmu7VimFu3BoIgAxxpmm2J05dvD0HT3yu10vuqU{ name:'wanghao', admin:true, iat:1529035386, exp:1529121786}

若输出:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE1MjkwMzQ3MzMsImV4cCI6MTUyOTEyMTEzM30.swXojmu7VimFu3BoIgAxxpmm2J05dvD0HT3yu10vuqU

invalid signature

则表示签名不对,即verify 这个方法的参数是错误的。

使用方法

1 新建一个node项目,并为其安装环境

C:\Users\bnkj>cd desktopC:\Users\bnkj\Desktop>mkdir jwt-demoC:\Users\bnkj\Desktop>cd jwt-demoC:\Users\bnkj\Desktop\jwt-demo>npm init-y

执行结果:

Wrote toC:\Users\bnkj\Desktop\jwt-demo\package.json:{"name":"jwt-demo","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"keywords":[],"author":"","license":"ISC"}

2 为项目安装jsonwebtoken环境

C:\Users\bnkj\Desktop\jwt-demo>npm install jsonwebtoken

结果:

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN jwt-demo@1.0.0 No description
npm WARN jwt-demo@1.0.0 No repository field.

+ jsonwebtoken@8.5.1
added 15 packages from 10 contributors in 1.194s

1 package is looking for funding
  run `npm fund` for details

3 新建一个 js 文件 ,并在其中添加基础的框架代码

const jwt=require('jsonwebtoken')// Token 数据const payload={
  name:'wanghao',
  admin:true}// 密钥const secret='ILOVENINGHAO'// 签发 Tokenconst token= jwt.sign(payload, secret,{ expiresIn:'1day'})// 输出签发的 Token
console.log(token)// 验证 Token
jwt.verify(token, secret,(error, decoded)=>{if(error){
      console.log(error.message)return}
    console.log(decoded)})

注意两个函数:

sign:需要三个参数,分别是payload,secret , 和options ,表示一些其他选项

verify:需要三个参数,分别是携带信息的token ,密钥 secret , 和一个回调的方法,这个方法需要由两个参数,分别是 error ,返回错误信息,另一个是decoded , 返回该token解码的结果

4 在命令窗口下验证该Token

C:\Users\bnkj\Desktop\jwt-demo>node index.js

结果:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlLCJpYXQiOjE2MDg0Njk5OTQsImV4cCI6MTYwODU1NjM5NH0.7Mi8WrHAv0fWZnLV6DlkPqK_ExQ4f09Zrs8eiVzXRQs{ name:'wanghao', admin:true, iat:1608469994, exp:1608556394}

在项目中的使用方法

空 ,后续更新

  • 作者:你觉得这样嘿怕吗
  • 原文链接:https://blog.csdn.net/weixin_43648017/article/details/111464021
    更新时间:2022年8月7日10:15:55 ,共 5334 字。