98 # jwt

news2024/11/15 8:26:30

什么是 jwt

JSON WEB TOKEN (jwt) 是目前最流行的跨域身份验证解决方案。

解决问题:session 不支持分布式框架,无法支持横向扩展,只能通过数据库来保存会话数据实现共享,如果持久层失效就会出现认证失败。

优点:服务器不保存任何会话数据,即服务器变为无状态,使其更容易扩展。

jwt 组成

Header 头部

header 典型的由两部分组成:token 的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)。

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

将头部进行 base64 加密(该加密是可以对称解密的),得到 JWT 的第一部分

Payload 负载、负荷

它包含声明(要求),声明是关于实体(通常是用户)和其他数据的声明。

声明有三种类型: registered(标准中注册的声明), public(公共的声明)和 private(私有的声明)。

  • Registered claims: 一组预定义的声明,它们不是强制的,但是推荐。
  • Public claims: 可以随意定义。
  • Private claims: 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。

jwt 规定了 7 个官方字段(标准中注册的声明 (建议但不强制使用))

iss (issuer) jwt 签发人
exp (expiration time) jwt 过期时间
sub (subject) 主题 / jwt 所面向的用户
aud (audience) 受众 / 接收 jwt 的一方
nbf (Not Before) jwt 生效时间
iat (Issued At) jwt 签发时间
jti (JWT ID) 编号 / jwt 唯一身份标识

例子:

{
    "sub": '1234567890',
    "name": 'kaimo',
    "admin": true
}

对 payload 进行 Base64 编码就得到 JWT 的第二部分

Signature

对前两个部分的签名,防止数据篡改。

需要编码过的 header、编码过的 payload 连接组成的字符串,然后通过 header 中指定的签名算法进行加盐 secret 组合加密,然后就构成了 jwt 的第三部分。

例子:

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

Base64URL 算法

Base64 有三个字符:+/=,在 URL 里面有特殊含义,所以要被替换掉:

  • = 被省略
  • + 替换成 -
  • / 替换成 _

这个就是 Base64URL 算法。

jwt-simple 的使用

实现个登录跟检测是否登录功能

npm i jwt-simple koa-bodyparser

这里使用简单点的 jwt-simple,强一点的可以使用 jwtwebtoken

const Koa = require("koa");
const Router = require("@koa/router");
const bodyparser = require("koa-bodyparser");
const jwt = require("jwt-simple");

const app = new Koa();
let router = new Router();
app.use(bodyparser());
app.use(router.routes());

router.post("/login", async (ctx, next) => {
    let { username, password } = ctx.request.body;
    if (username === "admin" && password === "123456") {
        let token = jwt.encode(username, "kaimo");
        ctx.body = {
            err: 0,
            username,
            token
        };
    }
});
router.get("/validate", async (ctx, next) => {
    let authorization = ctx.headers.authorization;
    try {
        let r = jwt.decode(authorization, "kaimo");
        ctx.body = {
            err: 0,
            username: r
        };
    } catch (error) {
        ctx.body = {
            err: 1,
            message: error
        };
    }
});

app.listen(3000);

console.log("Server running at http://127.0.0.1:3000/");

控制台可以访问:

curl -v -X POST --data "username=admin&password=123456" http://localhost:3000/login

我这里直接使用的 postman

http://localhost:3000/login

在这里插入图片描述
访问 http://localhost:3000/validate
在这里插入图片描述

实现自己的 jwt

这个 base64urlUnescape 方法反解 base64 的方法,可以参考 jwt-simple 里的实现,是规定的解法。

在这里插入图片描述

下面实现自己的 jwt

const Koa = require("koa");
const Router = require("@koa/router");
const bodyparser = require("koa-bodyparser");
const crypto = require("crypto");

const app = new Koa();
let router = new Router();
app.use(bodyparser());
app.use(router.routes());

let kaimoJwt = {
    toBase64Url(base64) {
        return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
    },
    toBase64(content) {
        return Buffer.from(JSON.stringify(content)).toString("base64");
    },
    sign(content, secret) {
        return this.toBase64Url(crypto.createHmac("sha256", secret).update(content).digest("base64"));
    },
    encode(payload, secret) {
        console.log("进入 kaimo-jwt--encode--->", payload, secret);
        let header = this.toBase64Url(
            this.toBase64({
                typ: "JWT",
                alg: "HS256"
            })
        );
        let content = this.toBase64Url(this.toBase64(payload));
        let sign = this.sign([header, content].join("."), secret);
        return [header, content, sign].join(".");
    },
    base64urlUnescape(str) {
        str += new Array(5 - (str.length % 4)).join("=");
        return str.replace(/\-/g, "+").replace(/_/g, "/");
    },
    decode(token, secret) {
        console.log("进入 kaimo-jwt--decode--->", token, secret);
        let [header, content, sign] = token.split(".");
        console.log("header---->", header);
        console.log("content---->", content);
        console.log("sign---->", sign);
        let newSign = this.sign([header, content].join("."), secret);
        console.log("newSign---->", newSign);
        if (sign === newSign) {
            // 将 base64 转化成字符串
            return JSON.parse(Buffer.from(this.base64urlUnescape(content), "base64").toString());
        } else {
            throw new Error("token 被篡改");
        }
    }
};

router.post("/login", async (ctx, next) => {
    let { username, password } = ctx.request.body;
    if (username === "admin" && password === "123456") {
        let token = kaimoJwt.encode(username, "kaimo");
        ctx.body = {
            err: 0,
            username,
            token
        };
    }
});

router.get("/validate", async (ctx, next) => {
    let authorization = ctx.headers.authorization;
    try {
        let r = kaimoJwt.decode(authorization, "kaimo");
        ctx.body = {
            err: 0,
            username: r
        };
    } catch (error) {
        ctx.body = {
            err: 1,
            message: error
        };
    }
});

app.listen(3000);

// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.ImFkbWluIg.prJEZUHxS0PtLnjZ0RwhUyQ-4HkANXZVAlIHU3ZNh7k

console.log("Server running at http://127.0.0.1:3000/");

效果也是一样的

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

强化学习问题(二)--- ERROR: Failed building wheel for box2d-py

错误:Could not build wheels for box2d-py, which is required to install pyproject.toml-based projects pyproject.toml-based projects:意思是缺少依赖包,对于box2d就是缺少swig 注意:安装python对应的swig版本 解决1&…

2023 NewStarCTF --- wp

文章目录 前言Week1MiscCyberChefs Secret机密图片流量!鲨鱼!压缩包们空白格隐秘的眼睛 Web泄露的秘密Begin of UploadErrorFlaskBegin of HTTPBegin of PHPR!C!E!EasyLogin CryptobrainfuckCaesars SecertfenceVigenrebabyrsaSmall dbabyxorbabyencodin…

CART 算法——决策树

目录 1.CART的生成: (1)回归树的生成 (2)分类树的生成 ①基尼指数 ②算法步骤 2.CART剪枝: (1)损失函数 (2)算法步骤: CART是英文“class…

【Java 进阶篇】创建 HTML 注册页面

在这篇博客中,我们将介绍如何创建一个简单的 HTML 注册页面。HTML(Hypertext Markup Language)是一种标记语言,用于构建网页的结构和内容。创建一个注册页面是网页开发的常见任务之一,它允许用户提供个人信息并注册成为…

Logo制作方法大公开:初学者也能学会的Logo设计教程

Logo是品牌或企业的象征,一个好的Logo可以提升品牌的认知度和美誉度。但是,很多人在设计自己的Logo时都会遇到一些困难。今天,我们将为你揭示Logo制作的技巧和秘密,让你轻松设计出专业水准的Logo。 首先,你需要注册并登…

FPGA project : sobel

实验目标: sobel算法,处理100X100灰度图像:野火logo 边缘检测: 边缘检测,针对的是灰度图像,顾名思义,检测图像的边缘,是针对图像像素点的一种计算,目的是标识数字图像…

VM虚拟机扩容

背景介绍 在实现3D结构光扫描算法移植到嵌入式平台jetson Xavier NX时,需要在windows的电脑上安装VM虚拟机搭载Ubuntu,然后在Ubuntu 18.04上安装开发软件Nsight Eclipse Edition,在该集成开发软件上交叉编译jetson aarc64架构上可运行的文件…

SAE-J1939-21 (超8字节)多包数据----CAN传输协议

一、协议数据单元(PDU) 1. 优先级(P) 消息优先级可从最高 0(000)设置到最低 7(111)。 2. 保留位(R) 保留此位以备今后开发使用。 3. 数据页(D…

中国移动咪咕、阿里云、华为“秀肌肉”,这届亚运会的“高光”不止比赛

文 | 智能相对论 作者 | 青月 竞技体育的发展,其实也可以看作是一部“技术进化史”。 在1924年的巴黎,广播首次进入奥运会,人们第一次可以通过报纸以外的方式了解奥运会。 1928年,在荷兰申办的阿姆斯特丹奥运会,高…

mi note3 刷入lineageos

下载 twrp TWRP是国外安卓爱好者开发的一款工具,全名为Team Win Recovery Project,主要作用包括刷机、备份 ,救砖。 https://twrp.me/xiaomi/xiaomiminote3.html 一般下载最新版本,mi note 3对应 https://dl.twrp.me/jason/twrp-…

Hadoop----Azkaban的使用与一些报错问题的解决

1.因为官方只放出源码,并没有放出其tar包,所以需要我们自己编译,通过查阅资料我们可以使用gradlew对其进行编译,还是比较简单,然后将里面需要用到的服务文件夹进行拷贝,完善其文件夹结构,通常会…

Android笔记(二):JetPack Compose定义移动界面概述

一、JetPack Compose组件概述 JetPack Compose是Google公司在2021年正式推出的声明式UI工具包。Compose库用于开发原生Android应用界面。它取代传统XML文件配置界面,不需要界面编辑工具,而是采用强大Kotlin API以及函数搭建移动应用界面,代码…

请求的转发和重定向

RequestDispatcher接口实现转发: jsp1上链接到Servlet,Servlet再转发(关键在这里怎么实现转发??) 演示index.html页面---->Servlet1(转发到)------>Servlet2 实现转发流程 1.用HttpServletReques…

如何使用CDN加载静态资源

文章目录 前言工具场景七牛云创建空间存储 控制台查看后言 前言 hello world欢迎来到前端的新世界 😜当前文章系列专栏:前端 🐱‍👓博主在前端领域还有很多知识和技术需要掌握,正在不断努力填补技术短板。(如果出现错误…

《机器学习》- 第3章 线性模型

文章目录 3.1 基本形式3.2 线性回归一元线性回归多元线性回归 3.3 对数几率回归3.4 线性判别分析3.5 多分类学习3.6 类别不平衡问题 3.1 基本形式 问题描述: 函数形式: 向量形式: 许多功能更为强大的非线性模型可在线性模型的基础上引入层…

Java项目如何防止SQL注入的四种方案

什么是SQL注入 SQL注入(SQL Injection)是一种常见的网络安全漏洞,它允许攻击者通过操纵应用程序的输入来执行恶意的SQL查询。这种漏洞发生在应用程序没有正确验证、过滤或转义用户提供的输入数据时。攻击者可以利用这个漏洞来执行未经授权的…

笔记本怎么录制屏幕?推荐3个实用技巧

在当今信息化快速发展的时代,笔记本录制屏幕成为人们日常生活中经常需要面对的问题。无论是办公、学习还是娱乐,录制屏幕都有着广泛的应用。可是笔记本怎么录制屏幕呢?接下来,本文将介绍3种常见的笔记本录制屏幕方法,我…

Python:Jupyter:OSError: Initializing from file failed

在学习Python的时候,我在进行导入外部文件的时候总是出现问题,总是乱导文件,可能碰巧文件导进去了,这次记录一下导入.csv文件失败的原因 read_csv时发生报错:OSError: Initializing from file failed filepathr"…

zabbix自定义监控内容和自动发现

6 目录 一、自定义监控内容: 1.明确需要执行的 linux 命令 2.创建 zabbix 的监控项配置文件,用于自定义 key: 3. 在 Web 页面创建自定义监控项模板: 3.1 创建模板: 3.2 创建监控项: 3.3 创建触发器&#…

C 语言数据类型概述

int 表示基本的整数类型, long, short, unsigned, signed 提供基本整数类型的变式. char 用于指定字符, 也可以表示较小的整数. float, double, long double 表示浮点数. _Bool 表示布尔值 (true 或者 false) _Complex 和 _Imaginary 分别表示复数和虚数. 通过这些关键字创…