node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)

文章目录

    • ⭐前言
    • ⭐ 环境准备
    • ⭐ 实现过程
      • ⭐ mysql 配置
      • ⭐路由前的准备
      • ⭐账号注册生成token
      • ⭐账号登录生成token
      • ⭐token登录
    • ⭐ 自测过程截图
    • ⭐总结
    • ⭐结束

yma16-logo

⭐前言

大家好,我是yma16,本文分享关于node实战——后端koa项目配置jwt实现登录注册(node后端就业储备知识)。
本文适用对象:前端初学者转node方向,在线大学生,应届毕业生,计算机爱好者。
node系列往期文章
node_windows环境变量配置
node_npm发布包
linux_配置node
node_nvm安装配置
node笔记_http服务搭建(渲染html、json)
node笔记_读文件
node笔记_写文件
node笔记_连接mysql实现crud
node笔记_formidable实现前后端联调的文件上传
node笔记_koa框架介绍
node_koa路由
node_生成目录
node_读写excel
node笔记_读取目录的文件
node笔记——调用免费qq的smtp发送html格式邮箱
node实战——搭建带swagger接口文档的后端koa项目(node后端就业储备知识)
jwt的发展

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在不同应用程序或服务之间安全地传输信息和声明。它最初由JWT工作组在2015年发布,现在已成为Web应用程序和API的常见身份验证和授权方案之一。JWT标准建立在JSON数据格式上,由三个部分组成:头部 header、载荷 payload、签名 Authorization。它们共同构成了一个包含声明信息的安全令牌。
JWT的发展可以追溯到OAuth 2.0协议,它是OAuth 2.0协议的一种扩展。JWT的目的是为了解决OAuth 2.0协议中的一些缺点,例如在使用OAuth 2.0协议时,每次请求都需要向OAuth服务器进行验证。使用JWT可以避免这种验证,因为JWT包含了所有必要的信息,服务器可以直接验证JWT的签名以确认用户的身份。
随着云计算和移动设备应用的普及,JWT已经成为了Web应用程序和API的一种标准身份验证和授权方案。同时,围绕JWT的生态系统也在不断壮大。例如,OAuth 2.0协议和OpenID Connect协议都已经支持JWT作为身份验证和令牌颁发方案。
总之,JWT是一种开放的、安全的、跨平台的身份验证和授权方案,它为不同应用程序和服务之间的安全通信提供了便利。随着时间的推移,JWT的发展已经越来越成熟,它将继续在Web应用程序和API的身份验证和授权领域发挥重要作用。

注册
register

登录
login

⭐ 环境准备

安装koa 需要的依赖

$ npm install koa koa-jwt koa-bodyparser koa2-cors koa-router koa2-swagger-ui mysql

官方文档用法

var Koa = require('koa');
var jwt = require('koa-jwt');var app = new Koa();// Custom 401 handling if you don't want to expose koa-jwt errors to users
app.use(function(ctx, next){return next().catch((err) => {if (401 == err.status) {ctx.status = 401;ctx.body = 'Protected resource, use Authorization header to get access\n';} else {throw err;}});
});// Unprotected middleware
app.use(function(ctx, next){if (ctx.url.match(/^\/public/)) {ctx.body = 'unprotected\n';} else {return next();}
});// Middleware below this line is only reached if JWT token is valid
app.use(jwt({ secret: 'shared-secret' }));// Protected middleware
app.use(function(ctx){if (ctx.url.match(/^\/api/)) {ctx.body = 'protected\n';}
});app.listen(3000);

初始化项目搭建请查看我写的这篇博客:node实战——搭建带swagger接口文档的后端koa项目(node后端就业储备知识)

⭐ 实现过程

注册过程分解:

  1. 查询用户名是否在user表存在
  2. 注册用户名已存在则登录
  3. 注册用户名不存在则插入用户数据

登录过程分解:

  1. 查询用户密码是否对应user表的数据
  2. 存在则根据用户名密码生成token
  3. 不存在抛出错误

token登录过程分解:

  1. 解析web端传递的token
  2. 拿出其中的用户名密码在数据库查询存在则登录成功

⭐ mysql 配置

封装mysql连接传递一个sql语句来运行即可

const mysql = require('mysql');const config ={host     : 'ip',user     : '账号',password : '密码',database : '数据库模式'
}
// 把这个方法抛出去
const execMysql=(sql)=>{return new Promise((resolve,reject)=>{// 连接mysqlconst connection = mysql.createConnection(config);try{connection.query(sql, function (error, results) {if (error){reject(error)};resolve(results)});}catch (e) {reject(e)}finally {connection.end()}})
};module.exports={execMysql
}

⭐路由前的准备

初始化router

const Router = require('koa-router');
const router = new Router();
const {execMysql}=require('../../utils/mysql/index')
const jwtToken = require("jsonwebtoken");// 唯一字符串
function uuid() {return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {var r = Math.random() * 16 | 0,v = c == 'x' ? r : (r & 0x3 | 0x8);return v.toString(16);});
}// 当前时间
const  getCurrentTime=() =>{const now = new Date()const year = now.getFullYear()const month = now.getMonth()const date = now.getDate()const hour = now.getHours()const minutes = now.getMinutes()const second = now.getSeconds()const formatNum = (n) => {return n > 9 ? n.toString() : '0' + n}return `${year}-${formatNum(month + 1)}-${formatNum(date)} ${formatNum(hour)}:${formatNum(minutes)}:${formatNum(second)}`
}

⭐账号注册生成token

封装注册写入sql 生成token

// 注册
router.post('/register', async (ctx) => {try{// 解析参数const bodyParams =  ctx.request.bodyconst {username,password} = bodyParams;if(!username||!password){return ctx.body = {code: 0 ,msg:'username or password is null'};}// 查询重复const search=await execMysql(`select count(1) as total from user where username='${username}';`)console.log('search',search)if(search[0].total>0){return ctx.body = {code: 0 ,msg:'user is exist'};}// id 唯一字符const id= uuid()const create_time=getCurrentTime()// 插入 数据const createRes=await execMysql(`INSERT INTO user (id,username,password,create_time) VALUES ('${id}', '${username}','${password}','${create_time}');`)// 更新token update_timeconst token=jwtToken.sign({username,password},"yma16-app", // secret{ expiresIn: 24 * 60 * 60 } // 60 * 60 s)const update_time=getCurrentTime()const tokenRes=await execMysql(`update user set token='${token}', update_time='${update_time}' where username='${username}';`)ctx.body = {code:200,data:{createSqlData:createRes,tokenSqlData:tokenRes},msg:' insert success',token:token};}catch (e) {ctx.body = {code:0,msg:e};}
});

⭐账号登录生成token

账号密码生成token

// 获取token
router.post('/token/gen', async (ctx) => {try{// 解析参数const bodyParams =  ctx.request.bodyconst {username,password} = bodyParams;// 查询 用户const search=await execMysql(`select count(1) as total from user where username='${username}' and password='${password}';`)if(search[0].total>0){// 更新token update_timeconst token=jwtToken.sign({username,password},"yma16-app", // secret{ expiresIn: 24 * 60 * 60 } // 60 * 60 s)const update_time=getCurrentTime()// 更新tokenconst tokenRes=await execMysql(`update user set token='${token}', update_time='${update_time}' where username='${username}';`)// 配置tokenconst AUTHORIZATION='Authorization'ctx.set(AUTHORIZATION,token)return ctx.body = {code:200,msg:'login success',token:token};}ctx.body = {code:0,msg:' login fail',};}catch (e) {ctx.body = {code:0,msg:e};}
});

⭐token登录

用户使用token登录

// token 登录
router.post('/token/login',async (ctx) => {try{// 解析参数const bodyParams =  ctx.request.bodyconst {token} = bodyParams;const payload = jwtToken.verify(token, 'yma16-app');console.log('token',token)const {username,password} =payload// 查询重复// 查询 用户const search=await execMysql(`select count(1) as total from user where username='${username}' and password='${password}';`)if(search[0].total>0){const last_login_time=getCurrentTime()// last_login_time  登录时间const tokenRes=await execMysql(`update user set last_login_time='${last_login_time}' where username='${username}' and password='${password}';`)return ctx.body = {code:200,msg:'login success',data:{username}};}ctx.body = {code:0,msg:' login fail',};}catch (e) {console.log('e',e)ctx.body = {code:0,msg:JSON.stringify(e)};}
})

⭐ 自测过程截图

生成token
gentoken
选择 authoration 为 beare token传递token 在 body的传递自定义token请求登录成功
token login success
数据库表写入 用户名、密码、token、创建时间、更新时间、最近登录时间 成功!
create sql data

⭐总结

注意事项:

  1. jwt 前后的 Authorization 保持一致
  2. 给注册页面开启白名单,不需要jwt校验
  3. 注意过去的expire时间,调试的时候调大一点

前后端加上aes加密更安全
后端node配置

const aesCrypto = require('crypto-js/aes');
const utf8Encode = require("crypto-js/enc-utf8")const secretKey = "yma16-app"// 加密
const encrypt = text => {let encryptedText = aesCrypto.encrypt(utf8Encode.parse(text), secretKey).toString();return encryptedText
}// 解密
const decrypt = text => {let decryptText = aesCrypto.decrypt(text, secretKey).toString(utf8Encode)console.log(decryptText)return decryptText.toString(utf8Encode);
}exports.aes = { encrypt, decrypt }

前端vue3配置
安装 crypto-js
定义加密解密方法

// @ts-ignore
import CryptoJS from 'crypto-js';export const globalEnv=()=>{return import.meta.env
};const key='yma16-app'
export const aes:any={//加密encrypt(word:string, keyStr?:any) {keyStr = keyStr ? key : 'yma16-app';var key = CryptoJS.enc.Utf8.parse(keyStr);var srcs = CryptoJS.enc.Utf8.parse(word);var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });return encrypted.toString();},//解密decrypt(word:string, keyStr?:any) {keyStr = keyStr ? key : 'abcdsxyzhkj12345';var key = CryptoJS.enc.Utf8.parse(keyStr);var decrypt = CryptoJS.AES.decrypt(word, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7});return CryptoJS.enc.Utf8.stringify(decrypt).toString();}
};

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!
gaoda-img

👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 最后,感谢你的阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot配置https

SSL : secure socket layer 是一种加密协议,SSL主要用于保护数据在 客户端和服务器之间的传输,,防止未经授权的访问和窃取敏感信息 在腾讯云申请ssl证书 申请了之后在我的域名中,,解析 解析了之后&…

Django 尝试SSE报错 AssertionError: Hop-by-hop headers not allowed 的分析

情况描述 近期计划测试一下django对日志打印的支持,一般都是用websocket的方式,想测试一下SSE (Server-sent events)的服务端推送,发现过程中存在报错: Traceback (most recent call last):File "D:\Software\Anaconda3\li…

API Testing v0.0.14 新增 gRPC, tRPC 协议的支持

api-testing 本次版本发布中的内容中,包含了两位高校同学的 contribution,其中屈晗煜在GitLink编程夏令营(GLCC)活动期间非常给力地增加了gRPC 协议的支持。 atest 版本发布 v0.0.14 atest 是一款用 Golang 编写的、开源的接口测试…

CSRF 篇

一、CSRF 漏洞: 1、漏洞概述: (1)一般情景: 利用已认证用户的身份执行未经用户授权的操作。攻击者试图欺骗用户在其不知情的情况下执行某些操作,通常是在受害者已经登录到特定网站的情况下。 &#xff0…

线程是如何创建的

线程不是一个完全由内核实现的机制,它是由内核态和用户态合作完成的。pthread_create 不是一个系统调用,是 Glibc 库的一个函数,所以我们还要去 Glibc 里面去找线索。 首先处理的是线程的属性参数。例如前面写程序的时候,我们设置…

国家数据局正式揭牌,数据专业融合型人才迎来发展良机

📕作者简介:热爱跑步的恒川,致力于C/C、Java、Python等多编程语言,热爱跑步,喜爱音乐的一位博主。 📗本文收录于恒川的日常汇报系列,大家有兴趣的可以看一看 📘相关专栏C语言初阶、C…

今天面了个00后测试员,让我见识到了内卷届的天花板

深耕IT行业多年,我们发现,对于一个程序员而言,能去到一线互联网公司,会给我们以后的发展带来多大的影响。 很多人想说,这个我也知道,但是进大厂实在是太难了,简历投出去基本石沉大海&#xff0…

MyBatis的增删改查

2023.10.29 本章学习MyBatis的基本crud操作。 insert java程序如下: ①使用map集合传参 Testpublic void testInsertCar(){SqlSession sqlSession SqlSessionUtil.openSession();//先将数据放到Map集合中,在sql语句中使用 #{map集合的key} 来完成传…

【c++|opencv】一、基础操作---1.图像读取

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 有关c操作opencv记录 1. 正文 1.1 图像读取、显示、保存 // 读取、显示、保存图像#include <opencv2/opencv.hpp> #include <iostream>us…

除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂…

Xilinx 7 系列 1.8V LVDS 和 2.5V LVDS 信号之间的 LVDS 兼容性

如果通过LVDS进行接口&#xff0c;可以按照以程图中的步骤操作&#xff0c;以确保满足正确使用LVDS的所有要求。 40191 - 7 系列 - 1.8V LVDS 和 2.5V LVDS 信号之间的 LVDS 兼容性 与LVDS兼容驱动器和接收器连接时&#xff0c;7系列LVDS和LVDS_25输入和输出应该不存在兼容性问…

合肥中科深谷嵌入式项目实战——人工智能与机械臂(四)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 作者&#xff1a;爱吃饼干的小白鼠。Python领域优质创作者&#xff0c;2022年度博客新星top100入围&#xff0c;荣获多家平台专家称号。…

3.6每日一题(线性方程求通解)

1、判断类型选择方法&#xff1a;发现以y为未知函数&#xff0c;以x为自变量&#xff0c;不符合我们学过的类型 2、此时有两种方法&#xff1a; &#xff08;1&#xff09;x 与 y 对调&#xff0c;此时 x 为未知函数&#xff0c;y 为自变量 &#xff08;2&#xff09;变量代换…

【Linux精讲系列】——yum软件包管理

​作者主页 &#x1f4da;lovewold少个r博客主页 ⚠️本文重点&#xff1a;Linux系统软件包管理工具yum讲解 &#x1f604;每日一言&#xff1a;踏向彼岸的每一步&#xff0c;都是到达彼岸本身。 目录 前言 Linux系统下的软件下载方式 yum 查看软件包 如何安装软件 如何卸…

Apollo上机实践:一次对自动驾驶技术的亲身体验

上机实践 概述自动驾驶通信分布式系统开发模式开发工具 自动驾驶感知传感器特性感知流程及算法部署感知模型 自动驾驶决策规划决策规划流程和算法使用 Dreamview 进行控制在环的规划调试开发规划场景和算法 福利活动 主页传送门&#xff1a;&#x1f4c0; 传送 概述 Apollo 是…

网络协议--TCP的交互数据流

19.1 引言 前一章我们介绍了TCP连接的建立与释放&#xff0c;现在来介绍使用TCP进行数据传输的有关问题。 一些有关TCP通信量的研究如[Caceres et al. 1991]发现&#xff0c;如果按照分组数量计算&#xff0c;约有一半的TCP报文段包含成块数据&#xff08;如FTP、电子邮件和U…

阿里云的OSS云存储的基本使用

阿里云官网&#xff1a;阿里云-计算&#xff0c;为了无法计算的价值 通过阿里云官网&#xff0c;登录进入用户的界面&#xff0c;在搜索框中输入OSS&#xff0c;然后进入阿里云的对象存储OSS的控制台。&#xff08;未开通的开通即可&#xff09; 创建 Bucket 点击【Bucket 列…

车载电子电器架构 —— 基于AP定义车载HPC

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

基于物联网、大数据、云计算、人工智能等技术的智慧工地源码(Java+Spring Cloud +UniApp +MySql)

智慧工地是指利用物联网、大数据、云计算、人工智能等技术手段&#xff0c;为建筑施工现场提供智能硬件及物联网平台的解决方案&#xff0c;实现建筑工地的实时化、可视化、多元化、智慧化、便捷化。智慧工地的建设目标是实现全天候的管理监控&#xff0c;提高施工效率和质量&a…

【OpenCV实现图像找到轮廓的不同特征,就像面积,周长,质心,边界框等等。】

文章目录 概要图像矩凸包边界矩形 概要 OpenCV是一个流行的计算机视觉库&#xff0c;它提供了许多图像处理和分析功能&#xff0c;其中包括查找图像中物体的轮廓。通过查找轮廓&#xff0c;可以提取许多有用的特征&#xff0c;如面积、周长、质心、边界框等。 以下是几种使用…