Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >聊一聊分布式会话的解决方案

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

作者头像
小熊学Java
发布于 2023-07-16 07:24:21
发布于 2023-07-16 07:24:21
46900
代码可运行
举报
文章被收录于专栏:全栈学习之路全栈学习之路
运行总次数:0
代码可运行

1、传统Session

1、传统session的概述

1、认证过程

1、用户向服务器发送用户名和密码。 2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。 3、服务器向用户返回一个 session_id,写入用户的 Cookie。 4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。 5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

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了

2、传统session实战

1、session服务搭建

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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、MongoDBMySQL 等常用存储的支持,Spring-Session 提供与 HttpSession 的透明整合,这意味着开发人员可以使用 Spring-Session 支持的实现方式,切换 HttpSession 至 Spring-Session

1、引入依赖

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 <!--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、配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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、引入依赖
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>4.4.0</version>
</dependency>
2、编写controller类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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的构成
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiamF2YXhpYW9iZWFyIn0.TOlrBtRrnJl_FfJ8YUnWLLHOIV6HKYzD1d0MBRlu9nU

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

header

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  '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
代码运行次数:0
运行
AI代码解释
复制
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

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

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小熊学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
10分钟搞定OAuth2.0授权服务
现在授权模式基本都是用OAuth2.0,什么OAuth2.0呢?这个有兴趣的同学可看阮大神的文章,今天主要给大家介绍一下OAuth 2.0的一种实现。
林老师带你学编程
2020/09/11
7610
jwt思维导图,让jwt不再难懂
一般情况下,web项目都是通过session进行认证,每次请求数据时,都会把jsessionid放在cookie中,以便与服务端保持会话。
java思维导图
2018/12/07
9780
搞懂单点登录SSO,基于SpringBoot+JWT实现单点登录解决方案
单点登录是目前比较流行的企业业务整合的解决方案之一。单点登录是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。例如:百度旗下有很多的产品,比如百度贴吧、百度知道、百度文库等,只要登录百度账号,在任何一个地方都是已登录状态,不需要重新登录。
章为忠学架构
2023/10/06
11.6K0
搞懂单点登录SSO,基于SpringBoot+JWT实现单点登录解决方案
【第十篇】单点登录原理和JWT实现
单点登录原理及JWT实现 波波烤鸭 一、单点登录效果   首先我们看通过一个具体的案例来加深对单点登录的理解。案例地址:https://gitee.com/xuxueli0323/xxl-s
用户4919348
2022/05/23
1.1K0
【第十篇】单点登录原理和JWT实现
不会吧,不会吧,不会还有人看了这篇文章还不精通JWT吧
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
上分如喝水
2021/08/16
3K0
不会吧,不会吧,不会还有人看了这篇文章还不精通JWT吧
JWT详解「建议收藏」
这种基于token的认证方式相比传统的session认证方式更节约服务器资源,并且对移动端和分布式更加友好。其优点如下:
全栈程序员站长
2022/08/25
1.6K0
JWT详解「建议收藏」
前后端分离--整套解决方案
前后端分离并不只是开发模式,而是web应用的一种架构模式。在开发阶段,前后端工程师约定好数据交互接口,实现并行开发和测试;在运行阶段前后端分离模式需要对web应用进行分离部署,前后端之前使用HTTP或者其他协议进行交互请求。
互扯程序
2019/05/09
4.1K0
前后端分离--整套解决方案
【秒杀】JWT-满足你水管服务器的状态信息携带方式
JWT,即为JSON Web Token,拆开来看,JSON是JavaScript的一种对象数据存储方式,Token则是令牌,组合在一起就是在Web应用上,使用令牌的JSON数据,乍一看还是有点抽象,
Ar-Sr-Na
2024/03/31
2620
【秒杀】JWT-满足你水管服务器的状态信息携带方式
单点登录(Single Sign On)解决方案
A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?
Java_老男孩
2019/09/20
6550
还不会用JWT?咱们通过单点登录来熟悉下
JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案之一,今天我们一起来揭开它神秘的面纱!
程序员小跃
2020/05/18
1K0
还不会用JWT?咱们通过单点登录来熟悉下
JWT入门简介
官网:https://jwt.io/ 文档:https://jwt.io/introduction/
编程随笔
2019/09/11
1.2K0
JWT入门简介
JWT(JSON Web Token)
HTTP Basic Auth 一种最古老的安全认证方式,这种方式就是简单的访问API的时候,带上访问的username和password,由于信息会暴露出去,所以现在也越来越少用了。
Se7en258
2021/05/18
1.1K0
JWT(JSON Web Token)
你们leader 可能都不知道的用户鉴权机制的原理
互联网年代,一个网站的用户数,就是这个网站的命脉,那么,这些用户的账户安全问题很成问题,于是行业大佬们,开始忧国忧民,研究出很多解决当下痛点的解决方案。从最开始的前后端不分离,研究出来的session-cookie,到后来基于前端存储的Token 验证 ,后来网站越来越多多了,为了不总是注册账号推出来的OAuth权限,以及一个公司项目太多了,为了防止重复登录开启的单点登录。
用户7413032
2022/03/09
1.4K0
你们leader 可能都不知道的用户鉴权机制的原理
whale系统实战开篇,聊聊用户认证
上次老猫和大家说过想要开发一个系统,从简单的权限开始做起,有的网友表示还是挺支持的,但是有的网友嗤之以鼻,认为太简单了,不过也没事,简单归简单,主要的还是个人技术的一个整合和实战。
程序员老猫
2021/04/23
6750
辩证的眼光搞懂 JWT 这个知识点
JWT 由三部分组成:Header,Payload,Signature 三个部分组成,并且最后由.拼接而成。
coder_koala
2020/03/03
1.4K0
辩证的眼光搞懂 JWT 这个知识点
手把手带你使用JWT实现单点登录
JWT(英文全名:JSON Web Token)是目前最流行的跨域身份验证解决方案之一,今天我们一起来揭开它神秘的面纱!
潘志的技术笔记
2024/07/02
4440
手把手带你使用JWT实现单点登录
JWT简介
JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。微服务常见的认证方案
一觉睡到小时候
2019/12/25
5570
『JWT』,你必须了解的认证登录方案
JWT 全称是 JSON Web Token,是目前非常流行的跨域认证解决方案,在单点登录场景中经常使用到。
古时的风筝
2020/08/20
1.2K0
JWT 到底应该怎么用才对?
JWT 全称为 JSON Web Token,是一份开源的标准协议,它定义了一种传输内容基于 JSON、轻量级、安全的数据传输方式。
松鼠专栏
2020/03/24
3.3K0
JWT 到底应该怎么用才对?
[1042]JWT加密
JWT,全称是Json Web Token, 是JSON风格轻量级的授权和身份认证规范,可实现无状态、分布式的Web应用授权;
周小董
2021/08/24
4760
相关推荐
10分钟搞定OAuth2.0授权服务
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验