聊一聊分布式会话的解决方案

news2024/9/28 13:26:49

1、传统Session

1、传统session的概述

1、认证过程

1、用户向服务器发送用户名和密码。

2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。

3、服务器向用户返回一个 session_id,写入用户的 Cookie。

4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。

5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

image-20230626152851627

2、存在的问题

扩展性不好,向上图中,存在两个服务器时,session不能共享

3、解决方案

1、session复制

将服务器1的session,复制到服务器2,同样将服务器2的session也复制到服务器1,这样两台服务器的session就一致了。像tomcat等web容器都支持session复制的功能,在同一个局域网内,一台服务器的session会广播给其他服务器。

缺点:同一个网段内服务器太多,每个服务器都会去复制session,会造成服务器内存浪费。

2、session黏性
3、Redis解决分布式session

解决方案如下:统一将用户信息存入redis中,从redis中去获取登录的用户信息,这样就可解决分布式session了

image-20230626155211581

2、传统session实战

1、session服务搭建

新建一个SpringBoot项目,编写controller类,代码如下👇

@RestController
@RequestMapping("/user")
public class UserController {

    /**
     * 登录接口
     * @param userName
     * @param password
     * @param session
     * @return
     */
    @GetMapping("/login")
    public String login(@RequestParam String userName, @RequestParam String password, HttpSession session){
        session.setAttribute("user", userName);
        return "登录成功";
    }

    /**
     * 获取用户信息接口
     * @param session
     * @return
     */
    @GetMapping("/info")
    public String getInfo(HttpSession session){
        return "登录用户为:" +  session.getAttribute("user");
    }
}

2、测试

1、访问登录接口

接口路径:http://localhost:8081/user/login?userName=javaxiaobear&password=123456

image-20230627155331472

2、访问获取用户接口

接口路径:http://localhost:8081/user/info

image-20230627155416855

3、为什么第二次访问,就获取了到了用户信息呢?

第一次访问登录接口,后端代码中我们有设置session,设置后,前端浏览器获取到了,就会把session的值set-cookie中,当第二次请求info接口时,会携带cookie访问到后端,通过cookie查询session,然后返回给客户端

image-20230627155820014

3、cookie的特性

1、cookie不能跨域

作为开发人员,我们都知道,localhost和127.0.0.1其实没啥区别,接下来我们访问下:http://127.0.0.1:8081/user/info,前提是localhost是成功登录的情况下

image-20230627161125175

发现获取不到用户信息

2、cookie存在tomcat中

我们模拟两台Java服务器,具体操作如下:配置是-Dserver.port=8082

image-20230627161558541

在8081服务器登录的情况下,访问:http://localhost:8082/user/info,发现获取不到登录用户,这是因为cookie是存在tomcat服务器中,获取不到!

2、Spring-Session

Spring-Session 提供了对Redis、MongoDB、MySQL 等常用存储的支持,Spring-Session 提供与 HttpSession 的透明整合,这意味着开发人员可以使用 Spring-Session 支持的实现方式,切换 HttpSession 至 Spring-Session

1、引入依赖

 <!--redis依赖配置-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

2、配置

server:
  port: 8081
spring:
  data:
    redis:
      port: 6379
      host: 127.0.0.1
      password: 123456
  session:
    store-type: redis
    timeout: 3000

3、测试

重新启动系统,依次访问:

  • http://localhost:8081/user/login?userName=javaxiaobear&password=123456
  • http://localhost:8081/user/info
  • http://localhost:8082/user/info

发现访问8082服务器时,也访问成功

3、JWT

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

官网:https://github.com/auth0/java-jwt

1、实战

1、引入依赖

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.4.0</version>
</dependency>

2、编写controller类

private static final String JWT_KEY = "javaxiaobear";

@GetMapping("/loginWithJwt")
public String loginWithJwt(@RequestParam String userName, @RequestParam String password){
    Algorithm algorithm = Algorithm.HMAC256(JWT_KEY);
    String token = JWT.create()
            .withClaim("user", userName)
            .sign(algorithm);
    return token;
}

@GetMapping("/infoWithJwt")
public String infoWithJwt(@RequestHeader String token){
    Algorithm algorithm = Algorithm.HMAC256(JWT_KEY);
    JWTVerifier verifier = JWT.require(algorithm)
            // reusable verifier instance
            .build();
    DecodedJWT verify = verifier.verify(token);
    return verify.getClaim("user").asString();
}

3、测试

登录接口:http://localhost:8081/user/loginWithJwt?userName=javaxiaobear&password=123456

image-20230628110821735

获取登录用户信息:localhost:8081/user/infoWithJwt

image-20230628111802378

响应:javaxiaobear

还有一种方法把获取到的token解析出来,https://jwt.io/专门解码的网站

image-20230628111933567

2、分析

1、JWT的构成

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiamF2YXhpYW9iZWFyIn0.TOlrBtRrnJl_FfJ8YUnWLLHOIV6HKYzD1d0MBRlu9nU

token存在两个点,也就是分成了三段,第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).

header

jwt的头部承载两部分信息:

  • 声明类型,这里是jwt
  • 声明加密的算法 通常直接使用 HMAC SHA256

完整的头部就像下面这样的JSON:

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

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.

payload

载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明

标准中注册的声明 (建议但不强制使用) :

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

公共的声明 :公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

私有的声明 :私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

定义一个payload:

{
“sub”: “1234567890”,
“name”: “John Doe”,
“admin”: true
}

然后将其进行base64加密,得到Jwt的第二部分。

signature

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的)
  • payload (base64后的)
  • secret
    这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret'); 

将这三部分用.连接成一个完整的字符串,构成了最终的jwt
注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

好了,本文就到这里了!如果觉得内容不错的话,希望大家可以帮忙点赞转发一波,这是对我最大的鼓励,感谢🙏🏻

资料获取👇 最后面就是领取暗号,公众号回复即可!

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

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

相关文章

电子会议桌卡

一、产品描述 采用电子墨水显示屏作为显示屏&#xff0c;取代传统的纸质或LCD铭牌&#xff0c;高科技的外观设计和节能的显示解决方案&#xff0c;结合网络和移动APP&#xff0c;为用户提供更便捷的会议工作服务。 电子铭牌具有环保、节能、操作方便、实用范围广等特点。 本…

MAMP 无法启动 servers 问题

如果你是window10系统,在下载MAMP安装这个软件后,启动,报错,如下所示 [Tue Dec 01 00:52:15 2020] [warn] Init: Session Cache is not configured [hint: SSLSessionCache] [Tue Dec 01 00:52:16 2020] [warn] pid file D:/software/MAMP/bin/apache/logs/httpd.pid overwritt…

深度学习与神经网络

文章目录 引言1. 神经网络1.1 什么是神经网络1.2 神经元1.3 多层神经网络 2. 激活函数2.1 什么是激活函数2.2 激活函数的作用2.3 常用激活函数解析2.4 神经元稀疏 3. 设计神经网络3.1 设计思路3.2 对隐含层的感性认识 4. 深度学习4.1 什么是深度学习4.2 推理和训练4.3 训练的相…

chatgpt赋能python:用Python实现冒泡排序:提高排序算法效率

用Python实现冒泡排序&#xff1a;提高排序算法效率 在计算机科学中&#xff0c;排序算法是一项重要而基础的任务。其中&#xff0c;冒泡排序是最简单、最基础的算法之一。它的思路很简单&#xff1a;将数组中相邻的两个元素进行比较&#xff0c;并根据大小交换位置。通过多次…

篇章十二 Vue3开发

文章目录 Vue3.0Vue带来了什么一、创建Vue3.0工程1、使用 vue-cli 创建2、使用 vite 创建1、创建工程2、分析工程结构2.1、main.js文件中2.2、App.vue文件中 二、常用 Composition API1、Options API 存在的问题2、Composition API 的优势3、常用的Composition API① 拉开序幕的…

Nvidia jetson TX2挂载256gSD卡

ps:在开始之前要做一点儿准备工作&#xff1a;把SD卡插进去&#xff0c;如果插进去了&#xff0c;ubuntu桌面上会显示SD卡&#xff1a; 1. 查看256G硬盘信息 sudo fdisk -lu一般显示的应该是下面这种内容&#xff1a; 2.修改sd卡的模式 sudo mkfs -t ext4 /dev/mmcblk1p1…

Spring Boot 中的负载均衡

Spring Boot 中的负载均衡 负载均衡是分布式系统中非常重要的一个概念&#xff0c;它可以帮助我们将请求分摊到多个服务实例中&#xff0c;从而提高系统的可用性和性能。在 Spring Boot 中&#xff0c;负载均衡通常是通过 Ribbon 实现的。本文将深入探讨 Spring Boot 中的负载…

机器学习第二课(KNN算法)

文章目录 一、介绍KNN1.1 定义1.2 工作流程 二、自实现KNN2.1 问题2.2 步骤 一、介绍KNN 1.1 定义 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别&#xff0c;则该样本也属于这个类别。 涉及到距离的计算&#xff08;欧式距离&…

(43)绞盘

文章目录 前言 43.1 在哪里购买 43.2 连接和配置 43.3 任务期间的控制 43.4 视频 前言 Daiwa winch 是专门为无人机配送设计的高质量绞盘。该绞盘包括一个"线端检测开关"&#xff0c;可防止将线拉得太紧&#xff0c;从而使设备拉伤或断线。绞盘包括一个弹簧装置…

从流处理来深入理解消息队列

大家好&#xff0c;我是 方圆。在《数据密集型应用系统设计》这本书中关于流处理的部分提到了消息队列相关的知识&#xff0c;我觉得它对理解和之后使用消息队列中间件有很大的帮助&#xff0c;遂将其中重要的部分总结出来&#xff0c;但也更推荐大家去看原书&#xff0c;原文收…

一文了解Python中的运算符

目录 &#x1f969;1.1.算数运算符 &#x1f969;1.2.赋值运算符 &#x1f969;1.3.复合赋值运算符 &#x1f969;1.4.比较运算符 &#x1f969;1.5.逻辑运算符 &#x1f990;博客主页&#xff1a;大虾好吃吗的博客 &#x1f990;专栏地址&#xff1a;Python从入门到精通专栏 P…

Android通过连接USB读写SD卡(libaums方案)

Android通过连接USB读写SD卡 最近有一个需求是要求通过Usb扩展读取到SD卡的内容。可以从Usb存储设备拷贝文件到内置卡&#xff0c;也可以从内置卡文件拷贝到Usb存储。 1. 相关的引入包 implementation androidx.core:core-ktx:1.7.0implementation androidx.appcompat:appcompa…

基于PSO优化LSSVM的时序预测MATLAB实战

今天给大家分享PSO优化LSSVM的时序预测代码实战&#xff0c;主要从算法原理和代码实战展开。需要了解更多算法代码的&#xff0c;可以点击文章左下角的阅读全文&#xff0c;进行获取哦~需要了解智能算法、机器学习、深度学习和信号处理相关理论的可以后台私信哦&#xff0c;下一…

SQL-每日一题【196.删除重复的电子邮箱】

题目 表: Person 编写一个 SQL 删除语句来 删除 所有重复的电子邮件&#xff0c;只保留一个id最小的唯一电子邮件。 以 任意顺序 返回结果表。 &#xff08;注意&#xff1a; 仅需要写删除语句&#xff0c;将自动对剩余结果进行查询&#xff09; 查询结果格式如下所示。 示…

电脑密码忘了怎么解除?分享4个好方法!

我的电脑设置了一个密码&#xff0c;但刚刚想开电脑的时候怎么也想不到那个密码了&#xff01;电脑密码忘了怎么解除&#xff1f;有什么好的方法吗&#xff1f; 为电脑设置一个密码可以更好地保护我们的电脑数据。但有时候我们在输入密码时可能会忘记密码&#xff0c;这将导致我…

考虑学PMP认证的项目经理,听我一句劝

早上好&#xff0c;我是老原。昨天3月份的考试成绩出了&#xff0c;我的朋友圈跟过年似的。 参加完3月的考试的同学体感普遍不是很好&#xff0c;本以为大家能过就很优秀了嘛&#xff0c;没想到是3A满天飞…… 我结合自己和一些同学的备考经历&#xff0c;分享一些备考思路。 …

【c++】并行编程:OpenMP入门

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍OpenMP入门。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&#x1f9…

“希尔排序:打破时间瓶颈的排序算法 “

文章目录 &#x1f50d;什么是希尔排序&#x1f511;希尔排序分组思想&#x1f4c8;希尔排序的优缺点&#x1f468;‍&#x1f4bb;希尔排序代码剖析 &#x1f50d;什么是希尔排序 希尔排序&#xff08;Shell Sort&#xff09;是插入排序的一种高效率的改进版本&#xff0c;也…

浏览器缓存方式有哪些(cookie、localstorage、sessionstorage)

浏览器缓存方式 概要 http缓存 基于HTTP协议的浏览器文件级缓存机制 websql 只有较新的chrome浏览器支持&#xff0c;并以一个独立规范形式出现 indexDB 一个为了能够在客户端存储可观数量的结构化数据&#xff0c;并且在这些数据上使用索引进行高性能检索的 API Cooki…

v-model双向绑定指令

文章目录 前言v-model.lazy 延迟同步v-model.trim 去掉空格 前言 v-model指令是Vue.js中实现双向数据绑定的一种重要机制。它可以将表单控件的值与Vue.js实例中的数据进行双向绑定&#xff0c;即当表单控件的值发生变化时&#xff0c;Vue.js实例中的数据也会随之更新&#xff…