当前位置: 首页 > news >正文

JWT登录验证前后端设计与实现笔记

设计内容

前端

  1. 配置全局前置路由守卫
  2. axios拦截器
  3. 登录页面和主页

后端

  1. JWT的封装
  2. 登录接口
  3. 中间件放行
  4. mysql数据库的连接
    在这里插入图片描述

详细设计

路由设计

配置全局前置守卫,如果访问的是登录页面则放行,不是则进入判断是否有token,没有则拦截回到登录页面,有则放行访问。

router.beforeEach((to, from, next) => {//如果是访问Login,则直接通过if(to.name==='Login'){next();}else{//如果没有token则进入登录页面if(!localStorage.getItem("token")){next({path:'/login'});}else{next();}}
});

axios拦截器

配置响应拦截器,拿到后端传来的token并保存到localStorage中,如果后端传回来了401错误(token失效),就会删除localStorage中的token并回到登录页面。

// 响应拦截
axios.interceptors.response.use(function (response) {//拿到响应里的tokenconsole.log(response);const authorization  = response.data.token;console.log(authorization);authorization && localStorage.setItem("token",authorization);return response;}, function (error) {const { status } = error.response;if(status===401){localStorage.removeItem("token");router.push("/login");}return Promise.reject(error);});

配置请求拦截器,把localStorage中的token加到请求头中的Authorization中。

//请求拦截
axios.interceptors.request.use(function (config) {const token = localStorage.getItem("token");//请求时带上token,给后端认证config.headers.Authorization = `${token}`;return config;}, function (error) {return Promise.reject(error);});

登录页面和主页

在这里插入图片描述
登录方法写得比较简单,请求登录接口,判断后端返回的结果。

LoginHandle(){if(this.loginForm.password || this.loginForm.username){axios.post("http://localhost:3000/login",this.loginForm).then(res=>{if(res.data.status == "success"){this.$router.push("/mainbox");}else{ElMessage.error('用户名或密码错误!');}})}else{ElMessage.error('请填写账号和密码!');}
}

访问主页时会请求后端的接口,主页请求时所携带的token给后端处理,后端会判断 token是否过期,如果过期后端就回应401错误码,401错误码被axios的响应拦截器处理,跳回登录页面。

mounted(){this.getIndex();
},
methods:{getIndex(){axios.get('http://localhost:3000/bill').then(res=>{console.log(res.data);})}
}

JWT封装

JWT是JSON Web Token的缩写,jsonwebtoken这个模块有两个常用的方法,sign()和verify()作用分别是生成token和验证token,sign()方法需要3个基本的参数,1.加密内容,2.密钥,3.过期时间。verify()方法有2个基本参数,1.加密内容,2.密钥。

const jwt = require("jsonwebtoken");
const secret = "samrol";
const JWT = {generate(value,expires){return jwt.sign(value,secret,{expiresIn:expires});},verify(token){try{return jwt.verify(token,secret);}catch(error){return false;}}
}
module.exports = JWT;

登录接口

访问/login时后端会做:拿到前端请求带过来的账户和密码,连接数据库,查询登录信息是否正确,不正确则回应登录错误给前端,信息正确:生成token,把token添加到header的Authorization里,返回成功信息。

const express = require("express");
const router = express.Router();
const mysql2 = require("mysql2");
const JWT = require("../util/JWT");
const getDBConfig = require("../util/mysql");router.post("/",async (req,res)=>{const {username,password} = req.body;const config = getDBConfig();const promisePool = mysql2.createPool(config).promise();var user = await promisePool.query(`select * from user where name=? and password=?`,[username,password]);//登陆成功if(user[0].length>0){//生成tokenconst token = JWT.generate({username,password},"10s");//设置头部res.header("Authorization",token);res.send({status:"success",message:"登录成功",token});}else{res.send({status:"error",message:"用户名或密码错误"});}
})module.exports = router;

补充一个数据库连接配置

function getDBConfig(){return{host:'127.0.0.1',port:3306,user:'root',	password:'',database:'vue_test',}
}module.exports = getDBConfig;

接口拦截中间键

接收到的每次请求都需要通过这个中间件,如果是login接口则直接放行,其他的则需要通过验证前端携带的token是否过期来判断能否放行,如果过期则返回401错误码来提醒用户token过期需要重新登录。

app.use((req,res,next)=>{if(req.url==="/login"){next();return;}const token = req.headers['authorization']//.split(" ")[1];if(token){var payload = JWT.verify(token);if(JWT.verify(token)){const newToken = JWT.generate({username:payload.username,password:payload.password,},"10s");res.header("Authorization",newToken);next();}else{res.status(401).send({errCode:"-1",errorInfo:"token过期!"});}}
})

相关文章:

  • c# B树
  • 记录 | 验证pytorch-cuda是否安装成功
  • 【天幕系列 02】开源力量:揭示开源软件如何成为技术演进与社会发展的引擎
  • Apache 神禹(shenyu)源码阅读(一)——Admin向Gateway的数据同步(Admin端)
  • 【深度学习:DICOM 注释工具】在 DICOM 注释工具中寻找的 7 个功能
  • 【论文精读】GPT2
  • Excel练习:折线图突出最大最小值
  • 第二十九回 施恩三入死囚牢 武松大闹飞云浦-分布式版本控制系统Git使用
  • Html的<figure><figcaption>标签
  • 突破编程_C++_基础教程(输入、输出与文件)
  • NLP_Transformer架构
  • Code Composer Studio (CCS) - Current and Local Revision
  • HDR 摄影
  • 第三百四十九回
  • 基于Qt数据库项目实现(Sqlite3为例)|考查数据库、表格(QTableView 显示)(进阶)
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • MQ框架的比较
  • SAP云平台里Global Account和Sub Account的关系
  • SpingCloudBus整合RabbitMQ
  • WePY 在小程序性能调优上做出的探究
  • 关于for循环的简单归纳
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 老板让我十分钟上手nx-admin
  • 你不可错过的前端面试题(一)
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 我这样减少了26.5M Java内存!
  • 原生Ajax
  • linux 淘宝开源监控工具tsar
  • (31)对象的克隆
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (搬运以学习)flask 上下文的实现
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (剑指Offer)面试题34:丑数
  • (一)Dubbo快速入门、介绍、使用
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转) Android中ViewStub组件使用
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .NET Core跨平台微服务学习资源
  • .net 简单实现MD5
  • .Net8 Blazor 尝鲜
  • .net反编译的九款神器
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET轻量级ORM组件Dapper葵花宝典
  • @html.ActionLink的几种参数格式
  • @SuppressWarnings(unchecked)代码的作用
  • @TableId注解详细介绍 mybaits 实体类主键注解
  • [2016.7.test1] T2 偷天换日 [codevs 1163 访问艺术馆(类似)]
  • [ACM] hdu 1201 18岁生日
  • [android] 练习PopupWindow实现对话框
  • [C#]OpenCvSharp结合yolov8-face实现L2CS-Net眼睛注视方向估计或者人脸朝向估计