学习笔记-Cookie、Session、JWT

目录

一、验证码的生成与校验

1. 创建生成验证码的工具类

2. 写一个 Controller

3. 实现验证码验证

1. 获取验证码

2. 验证码请求过程

3. 验证码的校验

4. 原理说明

5. 验证

 6. 总结

二、JWT登录鉴权

1. 为什么要做登录鉴权?

2. 什么是 JWT 

3. JWT相比传统的鉴权方式的优点

1. Session 认证

2. Session 认证的缺点

3. JWT 的优点

4. 创建 JWT

1. 引入依赖

2. 创建JWT 工具类

3. 生成一个token

5. 使用 JWT

1. Vue 导入依赖

2. 前端创建 Cookie 工具类

3. 在登录组件设置 token

4. 判断是否有 token

5. 发送 token

6. 服务器获取token


在登录页面加入图形验证码

一、验证码的生成与校验

1. 创建生成验证码的工具类

package com.Util;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;public class ImageCodeUtils {/*** 图片的宽度*/private int width = 160;/*** 图片的高度*/private int height = 40;/*** 验证码字符个数*/private int codeCount = 4;/*** 验证码干扰线数*/private int lineCount = 20;/*** 验证码*/private String code = null;private BufferedImage buffImg = null;Random random = new Random();public ImageCodeUtils() {createImage();}public ImageCodeUtils(int width, int height) {this.width = width;this.height = height;createImage();}public ImageCodeUtils(int width, int height, int codeCount) {this.width = width;this.height = height;this.codeCount = codeCount;createImage();}public ImageCodeUtils(int width, int height, int codeCount, int lineCount) {this.width = width;this.height = height;this.codeCount = codeCount;this.lineCount = lineCount;createImage();}/*** 生成图片*/private void createImage() {// 字体的宽度int fontWidth = width / codeCount;// 字体的高度int fontHeight = height - 5;int codeY = height - 8;// 图像bufferbuffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = buffImg.getGraphics();// 设置背景色g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);// 设置字体//Font font1 = getFont(fontHeight);Font font = new Font("Fixedsys", Font.BOLD, fontHeight);g.setFont(font);// 设置干扰线for (int i = 0; i < lineCount; i++) {int xs = random.nextInt(width);int ys = random.nextInt(height);int xe = xs + random.nextInt(width);int ye = ys + random.nextInt(height);g.setColor(getRandColor(1, 255));g.drawLine(xs, ys, xe, ye);}// 添加噪点float yawpRate = 0.01f;int area = (int) (yawpRate * width * height);for (int i = 0; i < area; i++) {int x = random.nextInt(width);int y = random.nextInt(height);buffImg.setRGB(x, y, random.nextInt(255));}// 得到随机字符String str1 = randomStr(codeCount);this.code = str1;for (int i = 0; i < codeCount; i++) {String strRand = str1.substring(i, i + 1);g.setColor(getRandColor(1, 255));// a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处g.drawString(strRand, i*fontWidth+3, codeY);}}/*** 得到随机字符串* @param n* @return*/private String randomStr(int n) {String str1 = "ABCDEFGHJKMNOPQRSTUVWXYZabcdefghjkmnopqrstuvwxyz1234567890";String str2 = "";int len = str1.length() - 1;double r;for (int i = 0; i < n; i++) {r = (Math.random()) * len;str2 = str2 + str1.charAt((int) r);}return str2;}/*** 得到随机颜色* @param fc* @param bc* @return*/private Color getRandColor(int fc, int bc) {if (fc > 255){fc = 255;}if (bc > 255){bc = 255;}int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}/*** 产生随机字体*/private Font getFont(int size) {Random random = new Random();Font[] font = new Font[5];font[0] = new Font("Ravie", Font.PLAIN, size);font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);font[2] = new Font("Fixedsys", Font.PLAIN, size);font[3] = new Font("Wide Latin", Font.PLAIN, size);font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);return font[random.nextInt(5)];}/*** 扭曲方法* @param g* @param w1* @param h1* @param color*/private void shear(Graphics g, int w1, int h1, Color color) {shearX(g, w1, h1, color);shearY(g, w1, h1, color);}private void shearX(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(2);boolean borderGap = true;int frames = 1;int phase = random.nextInt(2);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}private void shearY(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(40) + 10;boolean borderGap = true;int frames = 20;int phase = 7;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}public void write(OutputStream sos) throws IOException {ImageIO.write(buffImg, "png", sos);sos.close();}public BufferedImage getBuffImg() {return buffImg;}public String getCode() {return code.toLowerCase();}
}

2. 写一个 Controller

方法:前端访问,调用一下工具类生成验证码图片并返回

引入一下依赖

    <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency>

3. 实现验证码验证

1. 获取验证码

已经获取到验证码了,那么下一步怎么验证验证码呢?

2. 验证码请求过程

游览器那么多,服务器怎么知道是哪个游览器请求的?

这就可以使用到 Cookie 和 Session 

3. 验证码的校验

把字符串形式的验证码存到 Session

从Session 中获取验证码

4. 原理说明

5. 验证

提示验证码错误

先查看验证验证码的SessionID是否和获取验证码的SessionID 一样

可以看到,两个是不同的SessionID ,服务器根据ID去获取的值是不同的,所以验证码错误

那么为什么是不同的呢?

这是因为 Vue 开启了代理转发,所以每次请求的 Cookie中JSESSIONID 值会发生变化

如何解决呢?

官方的解决方案是代理转发的 请求 URL 前缀和服务器请求路径的项目名相同就没问题了

原来的请求路径

修改后的请求路径

注意:vue 的配置文件修改后需要重启

修改服务器的 URL ,修改后重启服务器

可以看到SessionID值是一样的了

验证成功

 6. 总结
  1. 会话开始:当一个用户首次访问一个网站,服务器会创建一个新的HttpSession对象,并生成一个唯一的会话ID(通常称为JSESSIONID)。
  2. 会话ID存储在Cookie中:服务器会在响应中包含一个Set-Cookie头,将这个会话ID作为cookie的一部分发送给浏览器。浏览器会存储这个cookie。
  3. 后续请求:当用户继续与网站交互时,浏览器会自动在每个后续请求中包含这个会话ID的cookie。这使得服务器能够识别出请求来自于哪个具体的会话。
  4. 服务器识别会话:服务器接收到请求后,会读取请求头中的cookie,提取出会话ID,然后使用这个ID在服务器端的会话存储中查找相应的HttpSession对象。
  5. 会话数据访问:一旦找到了HttpSession对象,服务器就可以从这个对象中读取或写入数据,比如用户信息、登录状态等。
  6. 会话结束:当用户关闭浏览器或会话超时,HttpSession对象会被销毁,除非服务器端有特别的配置来延长会话的存活时间。

二、JWT登录鉴权

JWT 全程 JSON Web Token

1. 为什么要做登录鉴权?

安全考虑,需要登录之后有操作权限了之后才能访问API接口

2. 什么是 JWT 

JWT(JSON Web Token)是一种在网络应用中用于身份验证和授权的令牌。你可以把它想象成一张电子版的“身份证”或“通行证”。

当你登录一个网站后,服务器会生成一个JWT,JWT 本质就是一条字符串,它把你的身份信息(比如用户名)保存到一个JSON字符串中,然后进行编码得到一个token 令牌,然后把这个令牌发回给你的浏览器。之后,每当你的浏览器想要访问受保护的资源时,它都会带上这个JWT。

3. JWT相比传统的鉴权方式的优点

1. Session 认证

我们知道 HTTP 是一种无状态的协议,HTTP协议在设计上不保留任何两次请求之间的信息。换句话说,当你向一个网站发送请求时,比如浏览一个网页,这个请求是独立的,它并不依赖于你之前对该网站做的任何事情。一旦服务器处理完你的请求并返回了响应,它就会忘记这次交互,就像从来没有发生过一样。

所以为了让服务器知道是谁在访问,我们会在游览器第一次登陆成功的时候,创建一个SessionID,然后把用户信息保存在 Session 对象中,最后把SessionID放到 Cookie 返回给游览器,这样下次游览器再访问的时候就知道是谁了,这就是基于Session 认证的过程

2. Session 认证的缺点

由于基于Cookie,而cookie无法跨域,所以session的认证也无法跨域

Session 是保存在服务器的,会使服务器的开销增大

3. JWT 的优点

简洁,

无状态存储,以加密的形式保存在客户端,

时效性,可以设置多少时间失效

4. 创建 JWT

1. 引入依赖
    <dependency><groupId>io.github.qyg2297248353.components</groupId><artifactId>jsonwebtoken-jjwt</artifactId><version>2.0.0</version></dependency>

2. 创建JWT 工具类
package com.Util;import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Map;
public class JwtUtil {// 私钥private static String privateKey = "12345678901234567890123456789012abcdefghijklmn";/** 生成token* @param claims 要加密的数据* @return* */public static String generateToken(Map<String, Object> claims) {// 使用JWT构建器构建令牌// 添加负载(claims),存储用户信息// 使用HS256算法和私钥进行签名,确保令牌的完整性和安全性// 最后将令牌以JSON格式编码,并压缩为紧凑字符串格式String token = Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, privateKey) // HS256加密,密钥长度必须大于等于256 bit.compact();return token;}
}
3. 生成一个token

在 Service 层调JWT工具类生成 token

登录成功后返回的 token

那么如何在每次请求都带上这个 token 呢?

可以把token 放到 Cookie 里

5. 使用 JWT

1. Vue 导入依赖
npm i js-cookie@2.2.0 -S 
2. 前端创建 Cookie 工具类

3. 在登录组件设置 token

引入token 工具类的方法

4. 判断是否有 token

在路由器文件的路由守卫中判断,如果有 token 则放行

验证

5. 发送 token

在自定义 axios 文件的请求拦截器中添加 token         自定义 axios

可以看到在登录成功后,请求头里有 token

6. 服务器验证token

服务器在哪个 Controller 里判断?在所有 Controller 都判断一下比较麻烦

这就可以使用拦截器,在拦截器中统一判断

1. 创建登录拦截器

2. 配置拦截器

在spring 配置文件配置拦截器

    <!--配置拦截器--><mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/>   <!--拦截所有请求--><mvc:exclude-mapping path="/Admin/Login"/>  <!--放行登录操作--><mvc:exclude-mapping path="/ImageCode/Captcha"/>   <!--放行请求验证码--><bean class="com.Interceptor.LoginInterceptor"/></mvc:interceptor></mvc:interceptors>

这样就可以在每次请求资源时都带有token,服务器根据 token 判断是否有权限访问数据

目前,在 Vue 的路由守卫有判断是否登录(token)以及在服务器的拦截器也有判断

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

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

相关文章

Open Interpreter - 开放解释器

文章目录 一、关于演示它是如何工作的&#xff1f;与 ChatGPT 的代码解释器比较 二、快速开始三、更多操作1、互动聊天2、程序化聊天3、开始新的聊天4、保存和恢复聊天5、自定义系统消息6、更改模型7、在本地运行 Open Interpreter终端Python上下文窗口&#xff0c;最大令牌 8、…

【Golang 面试 - 进阶题】每日 3 题(十四)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

python pip怎么安装包

按WinR键打开运行窗口&#xff0c;输入“cmd”&#xff0c;再按回车键&#xff0c;打开命令行窗口。 找到pip安装路径。 Python2/Python3安装路径是相同的&#xff0c;都在x:\Python xx\Scripts路径下。 拖动pip主应用程序到命令行窗口。 输入“install 模块/包名”&#xff…

【Golang 面试 - 进阶题】每日 3 题(十)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

PCIe总线-RK3588 PCIe RC初始化流程分析(十二)

1.简介 RK3588 PCIe RC的初始化涉及PCIe设备枚举、中断&#xff08;INTx、MSI、MSI-X&#xff09;配置、BAR配置、ATU配置、链路训练等&#xff0c;下面一一介绍。 2.初始化 当RC的模式为RK_PCIE_EP_TYPE时&#xff0c;平台驱动调用rk_add_pcie_port函数初始化RC&#xff0c…

【论文笔记】4D Millimeter-Wave Radar in Autonomous Driving: A Survey

原文链接&#xff1a;https://arxiv.org/abs/2306.04242 I. 引言 传统毫米波雷达&#xff08;3D毫米波雷达&#xff09;测量俯仰角的能力有限&#xff0c;数据通常仅包括距离、水平角和多普勒速度信息。此外&#xff0c;3D雷达数据存在噪声且分辨率低&#xff08;尤其是水平角…

python学习之路 - python的函数

目录 一、python函数1、函数介绍2、函数的定义3、函数的参数4、函数的返回值5、函数说明文档6、函数的嵌套调用7、变量的作用域8、综合案例9、函数与方法的区别 二、python函数进阶1、函数多返回值2、函数多种传参方式a、位置参数b、关键字参数c、缺省参数d、不定长参数 3、匿名…

【2024年华数杯C题老外游中国】(完整题解+代码+完整参考论文)

请问 352 个城市中所有 35200 个景点评分的最高分&#xff08;Best Score&#xff0c;简称 BS&#xff09;是多少&#xff1f;全国有多少个景点获评了这个最高评分&#xff08;BS&#xff09;&#xff1f;获评了这个最高评分&#xff08;BS&#xff09;景点最多的城市有哪些&am…

代码坏味道有24种?我看未必

微信公众号&#xff1a;牛奶 Yoka 的小屋 有任何问题。欢迎来撩~ 最近更新&#xff1a;2024/08/03 [大家好&#xff0c;我是牛奶。] 我在上一篇文章打开IDEA&#xff0c;程序员思考的永远只有两件事&#xff01;中&#xff0c;通过代码命名、重复代码、合格方法三个章节&#…

请你学习:前端布局3 - 浮动 float

1 标准流&#xff08;也称为普通流、文档流&#xff09; 标准流&#xff08;也称为普通流、文档流&#xff09;是CSS中元素布局的基础方式&#xff0c;它决定了元素在页面上的默认排列方式。这种布局方式遵循HTML文档的结构&#xff0c;不需要额外的CSS样式来指定元素的位置。…

MongoDB未授权访问漏洞

MongoDB未授权访问漏洞 mongodb数据库是由C编写&#xff0c;主要是为了提供web应可用扩展的一种高性能数据库。开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增、删、改、查高危动作)而且可以远程访问数据库。…

MySQL数据库学习笔记

1、数据库的相关概念 数据库是存储数据的仓库,数据是有组织的进行存储 (DataBase)DB. 数据库管理系统:操作和管理数据库的大型软件 DataBase Mangement System(DBMS) SQL 操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准。 1、Oracle 2、MySQL 3…

Face2V人脸向量开发包

Face2V SDK适用于需要人脸检测、人脸特征点和特征向量提取的应用&#xff0c;提供Web API和原生API。官方下载地址&#xff1a;Face2V SDK 。 1、目录组织 Face2V SDK开发包的目录组织说明如下&#xff1a; face2v_sdk | - core # 核心代码目录| -…

docker compose 安装 kafka

一 前置准备 创建 /data/kafkadata /data/zookeeper-1用于保存kafka和zookeeper的配置文件 kafkadata中创建三个文件夹 /kafka1 /kafka2 /kafka3&#xff0c;用于存放三个kafka节点的配置文件 zookeeper-1文件夹中创建 /conf /data /logs /datalog四个文件夹&#xff0c;用于…

【Nuxt】约定式路由和内置组件

约定式路由 手动创建&#xff1a; 或者还可以使用终端创建页面&#xff1a;nuxi-add-page npx nuxi add page about — about.vue npx nuxi add page about/index — about/index.vue <NuxtLink to"/"><button>Home</button></NuxtLink><…

对象存储及其相关概念介绍

对象存储是一种用来描述解决和处理离散单元&#xff08;这些离散单元被称作为对象&#xff09;的方法的通用术语。以下是关于对象存储的详细解析&#xff1a; 一、基本概念 定义&#xff1a;对象存储&#xff0c;也叫做基于对象的存储&#xff0c;是一种将数据以对象的形式进…

JavaScript基础——数据类型转换

显示数据类型转换 String()函数进行显示转换 Number()函数进行显示转换 Boolean()函数进行显示转换 隐式数据类型转换 算术运算隐式转化 比较操作隐式转化 赋值操作 在JavaScript中&#xff0c;数据类型转换是常见的操作&#xff0c;它允许将一种类型的数据转换为另一种…

立项技术路线选择

本章主要是简单聊聊技术路线&#xff0c;额涉及unity和虚幻&#xff0c;目的主要是给自己看的&#xff0c;记录下日期&#xff1a;2024.8.4 在今天&#xff0c;除游戏以外的厂商基本上采用c#的混合技术方案 如果需要的设备对象多。效果不需要极为精细&#xff0c;至少unity是绝…

(自用)MyLog 简单日志 .net6.0 等

appsettings.json {"LogOnOff": true //true 开启日志&#xff1b;false 关闭日志 } MyLog.cs using System.ComponentModel;namespace Namespace {/// <summary>/// 日志类型 枚举/// </summary>public enum LogType{[Description("调试日志&q…

【2024年华数杯全国大学生数学建模竞赛】C题:老外游中国 问题思路分析及Python代码实现

【2024 年华数杯全国大学生数学建模竞赛】C题&#xff1a;老外游中国 问题思路分析及Python代码实现 1 题目 最近&#xff0c;“city 不 city”这一网络流行语在外国网红的推动下备受关注。随着我国过境免签政策的落实&#xff0c;越来越多外国游客来到中国&#xff0c;通过网…