会话技术:Cookie、Session、JWT的优缺点分析与实践

news2024/9/19 20:25:48

登录认证

  • 会话技术
  • 方案一:Cookie
  • 方案二:Session
  • 方案三:令牌技术
  • JWT令牌
    • 介绍
    • 生成和校验
    • 登录下发令牌案例

会话技术

  • 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应
  • 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自同一浏览器,以便在同一次会话的多个请求间共享数据
  • 会话跟踪方案:
    • Cookie(客户端会话跟踪技术)
    • Session(服务端会话跟踪技术)
    • 令牌技术

为什么要共享数据呢?
由于 HTTP 是无状态协议,在后面请求中怎么拿到前一次请求生成的数据呢?此时就需要在一次会话的多次请求之间进行数据共享。

方案一:Cookie

cookie 是客户端会话跟踪技术,它是存储在客户端浏览器的。
比如第一次请求了登录接口,登录接口执行完成之后,我们就可以设置一个 cookie,在 cookie 当中存储用户的一些数据信息如用户名、id。
服务器端在给客户端响应数据的时候,会自动的将 cookie 响应给浏览器;浏览器接收到响应回来的 cookie 之后,会自动的将 cookie 的值存储在浏览器本地。接下来在后续的每一次请求中,都会自动的将浏览器本地所存储的 cookie 携带到服务端。
基于此,服务端可以判断获取的 cookie 的值是否存在,如果存在说明客户端之前已经登录完成了。这样我们就可以基于 cookie 在同一次会话的不同请求之间来共享数据。

为什么上面都是自动的进行的?
因为 cookie 是HTTP协议当中所支持的技术,而各大浏览器厂商都支持了这一标准。在 HTTP 协议官方给我们提供了一个响应头和请求头:

  • 响应头 Set-Cookie :设置Cookie数据的
  • 请求头 Cookie:携带Cookie数据的

在这里插入图片描述
案例测试

@Slf4j
@RestController
public class SessionController {
    // 设置Cookie
    @GetMapping("/c1")
    public Result cookie1(HttpServletResponse response){
        response.addCookie(new Cookie("login_username", "admin"));  //设置cookie/响应cookie
        return Result.success();
    }

    // 获取cookie
    @GetMapping("/c2")
    public Result cookie2(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("login_username")){
                System.out.println("login_username" + cookie.getValue());  //输出获取的指定cookie
            }
        }
        return Result.success();
    }
}

Cookie的优缺点

  • 优点:HTTP协议中支持的技术(像Set-Cookie 响应头的解析以及 Cookie 请求头数据的携带,都是浏览器自动进行的,是无需我们手动操作的)
  • 缺点:
    • 移动端APP无法使用 Cookie
    • 不安全,用户可以自己禁用 Cookie
    • Cookie 不能跨域

跨域:
假如前端部署在服务器192.168.150.200,端口80上,后端部署在 192.168.150.100,端口8080上;那么我们打开浏览器访问前端工程url:http://192.168.150.200/login.html,假设服务端访问接口地址为:http://192.168.150.100:8080/login,此时就存在跨域操作了。
如果服务器设置了一个Cookie,这个Cookie是不能使用的,因为Cookie无法跨域。
区分跨域的三个维度

协议 —— ip/域名 —— 端口

只要三个有一个维度不同,就是跨域操作。

方案二:Session

Session 是服务端会话跟踪技术,它是存储在服务器端的。Session 的底层其实就是基于Cookie来实现的。
如果浏览器是第一次请求服务器,这时服务器会自动创建一个会话对象 Session(每一个会话对象 Session 都有一个 ID);服务器给浏览器响应数据时,会将 Session 的 ID 通过 Cookie 响应给浏览器,Cookie的名字是固定的 JESSIONID=ID;浏览器会自动识别这个响应头,然后将Cookie存储在浏览器本地。后续每次请求浏览器都会将 Cookie 携带到服务端。
在这里插入图片描述
案例测试

	// 往session中存储数据
    @GetMapping("/s1")
    public Result session1(HttpSession session){
        log.info("HttpSession-s1: {}", session.hashCode());
        session.setAttribute("loginUser", "tom");  //往session中存储数据
        return Result.success();
    }

	//从session中获取数据
	@GetMapping("/s2")
    public Result session2(HttpServletRequest request){
        HttpSession session = request.getSession();
        log.info("HttpSession-s2: {}", session.hashCode());

        Object loginUser = session.getAttribute("loginUser");  //从session中获取数据
        log.info("loginUser: {}", loginUser);
        return Result.success(loginUser);
    }

Session 的优缺点

  • 优点:Session是存储在服务端的,安全
  • 缺点:
    • 服务器集群环境下无法直接使用Session
    • Cookie 的缺点

服务器集群环境为何无法使用Session?
集群下同一个项目会部署多份。用户会访问一台前置的服务器,叫负载均衡服务器,再将请求均匀的分发给后面的多台服务器。因此多个请求可能分发给了不同服务器,其他服务器当中就没有这个ID的会话对象Session了。

为了解决上面这些问题,现在企业开发中基本都会采样第三种方案,通过令牌技术来进行会话跟踪。

方案三:令牌技术

令牌就是一个用户身份的标识,本质是一个字符串。
在这里插入图片描述
如果通过令牌技术来跟踪会话,在第一次请求(如登录)成功的时候,我们就可以生成一个令牌,,令牌就是用户的合法身份凭证;接下来在响应数据时,直接将令牌响应给前端;前端接收到令牌后,需要将这个令牌存储起来,可以存储在 cookie 中,也可存储在其他的存储空间(如 localStorage)当中。后续每次请求都需要将令牌携带到服务端,服务端检验令牌有效性。
令牌 的优缺点

  • 优点:
    • 支持 PC端、移动端
    • 解决集群环境下的认证问题
    • 减轻服务器的存储压力(无需在服务器端存储)
  • 缺点:
    • 需要自己实现(包括令牌的生成、令牌的传递、令牌的校验)

JWT令牌

介绍

JWT 全称:JSON Web Token(官网:https://jwt.io/)

  • 定义了一种简洁的、自包含的格式,用于在通信双方以 json 数据格式安全的传输信息。由于数字签名的存在,这种信息是可靠的。

    简洁:是指 jwt 就是一个简单的字符串。
    自包含:指 jwt 令牌看似是一个随机的字符串,但是我们可以根据自身的需求在 jwt 令牌中存储自定义的数据内容(如用户的相关信息)。
    简单来讲,jwt就是将原始的json数据格式进行了安全的封装,这样就可以直接基于jwt在通信双方安全的进行信息传输了。

JWT的组成:

  • Header(头):记录令牌类型、签名算法等。 例如:{“alg”:“HS256”,“type”:“JWT”}
  • Payload(有效载荷):携带一些自定义信息、默认信息等。 例如:{“id”:“1”,“username”:“Tom”}
  • Signature(签名):防止Token被篡改、确保安全性。结合header、payload,并加入指定秘钥,通过指定签名算法计算而来。
    正是因为签名的存在,所以整个 jwt 令牌是非常安全可靠的。
    在这里插入图片描述

JWT 如何将原始的 json 格式数据转为字符串的呢?
进行 Base64编码:一种基于64个可打印的字符(A-Z a-z 0-9 + /)来表示二进制数据的编码方式。此外还有等号用于补位。
签名部分是通过指定的签名算法计算出来的。


JWT令牌最典型的应用场景就是登录认证:
  1. 在浏览器发起请求来访问登录的接口,如果登录成功之后,我们需要生成一个jwt令牌,将生成的 jwt令牌返回给前端。
  2. 前端拿到jwt令牌之后,会将jwt令牌存储起来。在后续的每一次请求中都会将jwt令牌携带到服务端。
  3. 服务端统一拦截请求之后,先来判断一下这次请求有没有把令牌带过来,如果没有带过来,直接拒绝访问,如果带过来了,还要校验一下令牌是否是有效。如果有效,就直接放行进行请求的处理。

生成和校验

需要先引入 JWT 的依赖:

<!-- JWT依赖-->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

生成JWT令牌的代码实现:

@Test
public void testGenerateJwt(){
	HashMap<String, Object> claims = new HashMap<>();
	claims.put("id", 1);
	claims.put("name", "tom");
	// 构建 JWT 令牌
	String jwt = Jwts.builder()
			.signWith(SignatureAlgorithm.HS256, "itcitel")  //签名算法, 密钥
			.setClaims(claims)  //自定义内容(载荷)
			.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))  //设置有效期为1h
			.compact();//将JWT转换为紧凑的字符串表示:以Base64编码压缩头部和载荷,并在之后添加签名
	System.out.println(jwt);
}

在这里插入图片描述
下面校验生成的JWT令牌(解析):

@Test
public void testParseJwt(){
	Claims claims = Jwts.parser()
			.setSigningKey("itcitel")  //签名密钥(必须和生成令牌时使用的相同)
			.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcwNjUwMDQ5NH0.Bs_W_knSJ9hCFL-lwEB_kXlYr3rewgskF62AMJAA37k")
			.getBody();
	System.out.println(claims);
}

在这里插入图片描述

令牌解析后,可以看到id和过期时间,如果在解析的过程当中没有报错,就说明解析成功了。

登录下发令牌案例

@Slf4j
@RestController
@CrossOrigin
public class LoginController {
    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public Result login(@RequestBody User user){
        log.info("用户登录:{}", user);
        User u = userService.login(user);
        // 如果登录成功,生成令牌,下发令牌
        if (u != null){
            Map<String, Object> claims = new HashMap<>();
            claims.put("id", u.getId());
            claims.put("name", u.getUsername());

            String jwt = JwtUtils.generateJwt(claims);
            return Result.success(jwt);
        }
        return Result.error("用户名或密码错误");
    }
}

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

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

相关文章

Java语言程序设计——篇十七(2)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 欢迎大家&#xff1a;这里是我的学习笔记、总结知识的地方&#xff0c;喜欢的话请三连&#xff0c;有问题可以私信&#x1f333;&#x1f333;&…

vscode tailwind插件无提示

说明 Tailwind CSS IntelliSense插件 版本: v0.12.7 问题: 无代码提示 解决 降版本

string的常用函数

目录 一.string 的 构造函数 二. iterator&#xff08;迭代器&#xff09;&#xff08;类似指针&#xff0c;但不是指针&#xff09; 2.1 begin 和 end 2.2 rbegin 和 rend 三. Capacity 函数 3.1 size 函数 3.2 capacity 函数 3.3 resize 函数 3.4 reserve函数 …

MySQL 相关知识笔记

一、字符编码 MySQL 默认的编码是 utf8&#xff0c;仅支持三个字节的存储&#xff1b;utf8mb4 支持四个字节的存储。 二、数据库操作 查询 查询所有数据库&#xff1a;SHOW DATABASES;查询当前数据库&#xff1a;SELECT DATABASE(); 创建 CREATE DATABASE [IF NOT EXISTS] 数据…

搜维尔科技:Manus Prime 3 Mocap 数据手套VR手套动作捕捉手套

通过在设置中添加手动捕捉功能&#xff0c;轻松创建动画内容。非常适合独立Mocap、预可视化、现场表演流和V-tubing。即插即用符合行业标准具有无与伦比的易用性。 通过添加精确的手部和手指动作捕捉数据&#xff0c;为您的虚拟角色加入情感和个性。Manus Prime 3 Mocap 数据手…

欧拉函数.

欧拉函数 给定 n个正整数 ai&#xff0c;请你求出每个数的欧拉函数。 欧拉函数的定义 输入格式 第一行包含整数 n。 接下来 n行&#xff0c;每行包含一个正整数 ai。 输出格式 输出共 n行&#xff0c;每行输出一个正整数 ai的欧拉函数。 数据范围 1≤n≤100, 1≤ai≤2109 输入…

【逐行注释】MATLAB下的IMM-EKF代码

IMM-EKF 基于EKF的多模型交互。以CV和CT两个模型进行交互&#xff0c;这里对代码进行逐行注释。 注释较多&#xff0c;个人理解的时候如果有误&#xff0c;欢迎指正。 每一行都有注释&#xff1a; 模型概况 二维平面上的运动模型&#xff0c;由CV和CT构成&#xff0c;基于…

【机器学习-监督学习】支持向量机

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;…

Linux:Bash中的命令介绍(简单命令、管道以及命令列表)

相关阅读 Linuxhttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm1001.2014.3001.5482 在Bash中&#xff0c;命令执行的方式可以分为简单命令、管道和命令列表组成。这些结构提供了强大的工具&#xff0c;允许用户组合命令并精确控制其执行方式。以下是对这…

分享一个基于文本挖掘的微博舆情分析系统Python网络舆情监控系统Flask爬虫项目大数据(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

Comsol TPMS_Diamond多孔构型吸声性能仿真

TPMS_Diamond多孔构型是一种新型的吸声材料结构&#xff0c;它采用了三维打印技术制备而成。该构型的设计灵感来自于结晶体的晶格结构&#xff0c;通过将正方形的单元堆积并沿着特定方向旋转&#xff0c;形成了一种类似于钻石的多孔结构。 TPMS_Diamond多孔构型具有以下特点&a…

systemback制作Ubuntu自己的系统镜像

systemback制作Ubuntu自己的系统镜像 目录1.安装、制作2.解决镜像大于4GB的问题3.写入镜像到U盘&#xff14;.安装 目录 systemback制作Ubuntu自己的系统镜像 最近需要备份自己的系统&#xff0c;同时制作安装镜像在另一台笔记本上安装&#xff0c;这里找到了一款很不错的软件…

excel表格输入数据生成函数曲线图

1.新建一个excel表格&#xff0c;横向或者纵向输入x轴点的数据 下图以横向数据为例子&#xff0c;两个y轴数据&#xff0c;生成两个函数曲线 2.右键选中上面输入的数据&#xff0c;点击插入&#xff0c;选择你要构造的函数样式 3.选中带平滑散点图即可生成前面数据生成的函数 …

内存管理篇-06Per-CPU页帧缓存

per-CPU缓存是对伙伴系统的完善&#xff0c;也是伙伴系统中的一部分。再回顾一下zone结构体的内容&#xff0c;这里的__percpu *pageset实际上就是Per-CPU的实现机制&#xff0c;所以这里的内存实际上最少有三部分&#xff0c;&#xff08;1&#xff09;free_area管理了大部分的…

数学建模之Matlab快速入门--全

前言&#xff1a; 本文是之前学Matlab时候做的笔记&#xff0c;很适合快速入门数学建模中matlab和python是最常用的两个软件&#xff0c;现在本人更喜欢python去做数学建模 文章目录 界面介绍与操作快捷操作 数据类型数值型整型浮点型复型逻辑型字符型struct数组cell数组函数句…

区块链国赛第六套样题(关于运维)

任务1-2&#xff1a;区块链系统部署与运维 围绕食品安全溯源区块链平台部署与运维需求&#xff0c;进行项目相关系统、节点以及管理工具的部署工作。通过监控工具完成对网络、节点服务的监控。最终利用业务需求规范&#xff0c;完成系统日志、网络参数、节点服务等系统结构的维…

Jetson安装Archiconda3全过程

1. 下载Archiconda3 下载网址&#xff1a; 发布 Archiconda/build-tools --- Releases Archiconda/build-tools (github.com)​​​​​​ 2. 执行命令 bash ./Archiconda3-0.2.2-Linux-aarch64.sh 3. conda换源 conda config --add channels https://mirrors.tuna.tsing…

计算机网络-PIM-SM组播实验

一、概述 目前为止我们学习了组播转发网络中的PIM协议&#xff0c;PIM模型有两种&#xff1a; PIM-DM主要使用在网络规模较小&#xff0c;用户集中的组播网络中。 PIM-SM主要使用在网络规模较大&#xff0c;用户较为分散的组播网络中。PIM-SM基于组播模型又可以分为PIM-SM&…

5.Lab four —— Trap

首先切换traps分支 git checkout traps make clean RISC-V assembly 代码&#xff1a; #include "kernel/param.h" #include "kernel/types.h" #include "kernel/stat.h" #include "user/user.h"int g(int x) {return x3; }int f(…

AI预测体彩排3采取888=3策略+和值012路或胆码测试8月24日升级新模型预测第61弹

经过近60多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率非常高&#xff0c;已到达90%的命中率&#xff0c;这给喜欢打私菜的朋友提供了极高价值的预测结果~当然了&#xff0c;大…