jwt的基本介绍

news2024/12/23 23:04:14

说出我的悲惨故事给大家乐呵乐呵:公司刚来了一个实习生,老板让他写几个接口给我,我页面还没画完呢。他就把接口给我了,我敲开心,第一次见这么高效率的后端。但我很快就笑不出来了。他似乎不知道HTTP通信是无状态的。他不能识别登录的用户,只会把数据添加进数据库。虽然网络上有很多资料,但为了省时间,我打算写了简单的demo和他探讨一下,可能不太规范,希望大家多多指教。

JSON Web Token 简介

JSON Web Token 简称JWT,在HTTP通信过程中,进行身份认证。
好了,就说这么多,先上代码,因为有些概念说不好会把人转晕,手动操作后就容易理解了:
请添加图片描述

 /**
     * 
     * 实现流程:
     * 用户登录,服务器产生一个token(加密字符串)发送给前端,
     * 前端将token保存(想存哪就存哪)
     * 前端发起数据请求时携带token
     * 服务端验证token是否合法,合法继续操作,不合法终止操作
     * token的使用场景:无状态请求,保持用户的登录状态,第三方登录(token+auth2.0)
     */
   async function onFinished(e){
        //提交表单默认会跳转到新的页面,或者刷新整个页面
        //1.阻止默认事件
        e.preventDefault();

        //2.定义formData对象
        let formData = new FormData(e.target);
        let username = formData.get('username');
        let password = formData.get('password');

        console.log(username, password);
        try{
            const result = await  login(username, password);
            //save token to local storage
            storage.set('token', result.token)
            console.log(result)
        }catch(e){
            console.log(e)
        }
       
    }
export function login(username,password) {
  return axios.post('http://192.168.50.225:3000/login',{
        username,
        password
    })
}

node 中 jwt的使用

var express = require('express');
const jwt = require('jsonwebtoken');//加载包
const fs = require('fs');
const { dirname } = require('path');
var router = express.Router();
/**
 * login
 */

router.post('/login', function(req, res, next){

  console.log(req.body)//{ username: 'eqw', password: 'qweq' }
  //产生token默认算法hs256
  /**
   * 此方法接收两个参数
   * 第一个是要加密保存的数据(一个对象,不要放隐秘性的数据,如密码),
   * 第二个是要加密的私钥(一个字符串,越乱越好)
   */
  let token=jwt.sign(req.body,'rieryowqerdfkjhasdfqr');
  console.log(token);//返回一个加密字符串
  // 服务器签发的token
  //eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMTIzIiwiaWF0IjoxNTcwMDc2NjU5fQ.3FT6v8zVptdWGBILD1m1CRY6sCP1I3E947krUh_E3
  
  //我就不链接数据库了,将数据存入本地文件
  //fs.appendFile()方法的作用是:将指定的内容追加到文件中。如果该文件不存在,则创建该文件:
  fs.appendFile(__dirname+'/data.txt', JSON.stringify(req.body), function (err) {
    if (err) throw err;
    console.log('Saved!');
  });

  res.send({
    token,
    status:200,
    message:'success'
  })
});

module.exports = router;

前端登录:
只做演示实验,前端没有对密码加密勿怪
请添加图片描述
请添加图片描述

前端请求数据:
request.js

import axios from 'axios';
import { storage } from '../utils/localStorage';


axios.defaults.timeout = 5000
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';

//在请求头里验证是否有token
axios.interceptors.request.use(function (config) {
    const token=storage.get('token');
    console.log(token)
    if(token){
        config.headers['Authorization'] = 'Bearer ' + token;
    }else{
      //重定向到登录界面
    }
    return config;
  }, error => {
    console.log(error)
    Promise.reject(error)
  })

//请求响应
  axios.interceptors.response.use(function (response) {
    if (response.status === 401) {
  		//
    }
    return response;
  }, function (error) {
    return Promise.reject(error)
  })
  
  
  export default axios;

user.js

import axios from '../request';


export function login(username,password) {
  return axios.post('http://192.168.50.228:3000/login',{
        username,
        password
    })
}

export function getInfo(){
    return axios.get('http://192.168.50.228:3000/info');
}

后端验证token:

/**
 * 请求数据
 */

router.get('/info',function(req,res,next){
  //客户端请求数据的时候验证token
  //客户端传递过来的token
  console.log(req.headers.authorization)
  let tokens=req.headers.authorization.split(' ')[1];

  /**
   * verify接收两个参数,
   * 第一个参数是客户端传递过来的token,
   * 第二个参数是加密时的私钥;
   * 第三个参数是回调函数
   */

  jwt.verify(tokens,'rieryowqerdfkjhasdfqr',function (err,data) {
      console.log(err);//签名通过返回null,签名不通过返回err(JsonWebTokenError: invalid signature)	
      console.log(data);//	通过返回解密数据,失败返回unfinished

      fs.readFile(__dirname+'/data.txt',function(err, datas){
        if(err){
          res.writeHead(505,{'Content-Type':'text/html;charset=utf-8'});
          res.end({
            message:'500 服务器内部错误'
          })
          return;
        }
       
        //console.log(data,'database');//<Buffer 7b 22 75 73 65 72 6e 61 6d 65 22 3a 22 6d 69 61 6f 22 2c 22 70 61 73 73 77 6f 72 64 22 3a 22 6d 69 61 6f 31 32 33 22 7d>
        console.log(JSON.parse(datas.toString()));

        //从文件中直接读取到时Buffer ,把Buffer转成datas.toString() 字符串
        const user=JSON.parse(datas.toString());

        console.log(user.username===data.username,'-_-');
        if(user.username===data.username){
          res.send({
            data:[
              {id:1,name:"纸崩"},
              {id:2,name:"当怪兽来敲门"}
            ]
          })
        }else{
          res.writeHead(404,{'Content-Type':'text/html;charset=utf-8'});
          res.end({
            message:'token is error'
          })
        }
      })
  });
});

前端请求:
请添加图片描述
现在在来看概念:
HTTP通信是无状态的,因此客户端的请求到了服务端处理之后是无法返回给原来的客户端的。so,需要对访问的客户进行识别。
常用的做法是session机制:客户端在服务端登陆成功之后,服务端会生成一个sessionID,返回给客户端,客户端将sessionID保存到cookie中,再次发起请求的时候,携带cookie中sessionID到服务端,服务端会缓存该session,当客户端请求到来的时候,服务端就知道是哪个用户的请求,并将处理的结果返回给客户端,完成通信。
通过上面的分析,可以知道session存在以下问题:

  • session保存在服务端,当客户访问量增加时,服务端就需要存储大量的sesion会话,对服务器又很大的考验;

所以这里采用了JSON Web Token,JSON Web Token是怎么做的?
1.客户端通过用户名和密码登录服务器
2.服务端对客户端进行身份验证
3.服务端对该用户生成Token,返回给客户端
4.客户端将Token保存到本地浏览器,一半保存cookie中
5.客户端发起请求,需要携带该tooken
6.服务端收到请求后,首先验证该Token,之后返回数据。
服务端不需要存储token,只需要对Token中携带的信息进行验证即可;
无论客户端访问后台的哪台服务器,只要可以通过用户信息的验证即可。

参考资料:https://blog.csdn.net/weixin_44036436/article/details/102004739

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1067227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Glide源码分析

一&#xff0c;Glide一次完整的加载流程 下面的流程图是一次完整的使用Glide加载图片流程,时序图 二&#xff0c;Glide重要的类图 三&#xff0c;Glide加载图片 流程图

C语言数据结构 1.1 初学数据结构

数据结构的基本概念 数据结构在学什么&#xff1f; 如何用程序代码把现实世界的问题信息化 如何用计算机高效处理信息从而创造价值 数据&#xff1a; 数据元素、数据项&#xff1a; 数据元素——描述一个个体 数据对象——数据元素之间具有同样的性质 同一个数据对象里的数…

3. 无重复字符的最长子串(枚举+滑动窗口)

目录 一、题目 二、代码 一、题目 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 二、代码 class Solution { public:int lengthOfLongestSubstring(string s) {int _MaxLength 0;int left 0, right 0;vector<int>hash(128, 0);//ASCII…

【iOS】——仿写计算器

文章目录 一、实现思路二、实现方法三、判错处理 一、实现思路 先搭建好MVC框架&#xff0c;接着在各个模块中实现各自的任务。首先要创建好UI界面&#xff0c;接着根据UI界面的元素来与数据进行互动&#xff0c;其中创建UI界面需要用到Masonry布局。 二、实现方法 在calcu…

糖基转移酶特异性 -bg

糖基转移酶特异性 大多数糖基转移酶对其供体和受体底物都具有高度的特异性&#xff0c;这导致Saul Roseman及其同事提出了“一种酶 - 一种连接”假说。人B血型α1-3半乳糖基转移酶就是这一概念的例证。该酶催化糖基化反应&#xff0c;其中半乳糖以α键添加到受体底物上半乳糖残…

[0xGame 2023] week1

整理一下&#xff0c;昨天该第二周了。今天应该9点结束提交&#xff0c;等我写完就到了。 PWN 找不到且不对劲的flag 第1题是个nc测试&#xff0c;但也不完全是&#xff0c;因为flag在隐含目录里 高端的syscall 程序使用了危险函数&#xff0c;并且没有canary阻止&#xff0…

后端解决跨域(极速版)

header(Access-Control-Allow-Origin: *); header(Access-Control-Allow-Methods:*); 代表接收全部的请求&#xff0c;"POST,GET"//允许访问的方式 指定域&#xff0c;如http://172.20.0.206//宝塔的域名&#xff0c;注意不是&#xff1a;http://wang.jingyi.icu等…

文件上传笔记

一、上传的简单绕过&#xff1a; 1、若是上传的文件只在前端的代码中进行了过滤&#xff1a; &#xff08;1&#xff09;可以直接在开发者工具中删除相关代码&#xff1a; &#xff08;2&#xff09;也可以通过 burpsuite 绕过: 上传时&#xff0c;先提前修改 php 文件的后缀…

QT之可自由折叠和展开的布局

介绍和功能分析 主要是实现控件的折叠和展开&#xff0c;类似抽屉控件&#xff0c;目前Qt自带的控件QToolBox具有这个功能&#xff0c;但是一次只能展开一个&#xff0c;所以针对自己的需求可以自己写一个类似的功能&#xff0c;这里实现的方法比较多&#xff0c;其实原理也比较…

upload文件上传

参数格式 <el-upload :http-request"upload" class"upload" :show-file-list"false" :on-success"handleUploadSuccess"><el-button size"default" type"primary" style"margin:0 20px;">上…

分类预测 | MATLAB实现POA-CNN鹈鹕算法优化卷积神经网络多特征分类预测

分类预测 | MATLAB实现POA-CNN鹈鹕算法优化卷积神经网络多特征分类预测 目录 分类预测 | MATLAB实现POA-CNN鹈鹕算法优化卷积神经网络多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现POA-CNN鹈鹕算法优化卷积神经网络多特征分类预测&#xff0…

深入解读redis的zset和跳表【源码分析】

1.基本指令 部分指令&#xff0c;涉及到第4章的api&#xff0c;没有具体看实现&#xff0c;但是逻辑应该差不多。 zadd <key><score1><value1><score2><value2>... 将一个或多个member元素及其score值加入到有序集key当中。根据zslInsert zran…

02.Cesium源码编译及搭建开发环境

开始之前&#xff0c;默认你已经掌握了一定的前端知识&#xff0c;文章中用到的一些前端知识不再展开解释&#xff0c;如果你有不明白的地方&#xff0c;请自行学习。 另外&#xff0c;本篇文章及后续的文章首先会使用原生JS的方式 进行实例的开发&#xff0c;Vue版本会在后期文…

办公技巧:Excel日常高频使用技巧

目录 1. 快速求和&#xff1f;用 “Alt ” 2. 快速选定不连续的单元格 3. 改变数字格式 4. 一键展现所有公式 “CTRL ” 5. 双击实现快速应用函数 6. 快速增加或删除一列 7. 快速调整列宽 8. 双击格式刷 9. 在不同的工作表之间快速切换 10. 用F4锁定单元格 1. 快速求…

快速掌握批量合并视频

在日常的工作和生活中&#xff0c;我们经常需要对视频进行编辑和处理&#xff0c;而合并视频、添加文案和音频是其中常见的操作。如何快速而简便地完成这些任务呢&#xff1f;今天我们介绍一款强大的视频编辑软件——“固乔智剪软件”&#xff0c;它可以帮助我们轻松实现批量合…

ACE综述

1、ACE综述 ACE自适配通信环境&#xff08;ADAPTIVE Communication Environment&#xff09;是可自由使用、开放源码的面向对象&#xff08;OO&#xff09;框架&#xff08;framework&#xff09;&#xff0c;它实现了许多用于并发通信软件的核心模式。ACE提供了一组丰…

【juc】countdownlatch实现游戏进度

目录 一、截图示例二、代码示例 一、截图示例 二、代码示例 package com.learning.countdownlatch;import java.util.Arrays; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurr…

C++:模板(非类型模板参数、类模板的特化、模板的分离编译)

本文是 C&#xff1a;模板&#xff08;函数模板、类模板&#xff09; 该文的进阶部分&#xff0c;主要介绍模板非类型模板参数、类模板的特化、模板的分离编译这三部分。 目录 一、非类型模板参数 二、模板的特化 1.概念 2.函数模板特化 3.类模板特化 1.全特化 2.偏特…

Lua系列文章(1)---Lua5.4参考手册学习总结

windows系统上安装lua,下载地址&#xff1a; Github 下载地址&#xff1a;https://github.com/rjpcomputing/luaforwindows/releases 可以有一个叫SciTE的IDE环境执行lua程序 1 – 简介 Lua 是一种强大、高效、轻量级、可嵌入的脚本语言。 它支持过程编程&#xff0c; 面向对…

VScode配置Jupyter

环境 安装步骤 1、插件安装 2、更改pip加速源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 参考&#xff1a;vscode python配置pip源 ​​​​​​​ 【Python学习】Day-00 Python安装、VScode安装、pip命令、镜像源配置、虚拟环境 3、建…