替换Servlet容器的HttpSession实现集群中Session共享(With Redis)

深入解析Shiro Session管理:架构、集群实战与安全加固 在Java Web应用开发中,会话管理是构建安全、稳定用户交互体验的核心基础。其原理在于通过服务器端维护用户状态,实现请求间的身份与数据关联。这项技术的核心价值在于为分布式系统提供统一的状态管理能力,确保用户登录状态与上下文信息在集群环境下的一致性。典型的应用场景包括电商平台的购物车状态保持、后台管理系统的权限上下文传递以及高并发下的用户会话共享。本文聚焦于Apache Shiro框架的会话管理机制,通过剖析其SessionManager与SessionDAO的协作,并结合Redis缓存实现,详细阐述了如何 阅读详情

本文是我个人在开发web-security 安全框架中使用的方案。
在Web Server集群环境中需要实现 session 共享,一个很好的方法就是将 session 数据存放至 Redis 中。我打算在自己的安全框架中集成此功能,只需要几行配置就能自动让你的 web 项目集成 redis session 共享功能。

实现思路为:

将 Servlet 容器的HttpSession实现替换成自己的实现, 如RedisHttpSession。这样当在Controlelr中调用session.setAttr()此类方法时就可以执行自己的代码。我们编写一个Filter, 在调用chain.doFilter(req, resp)时,将HttpServletRequest对象替换成我们自定义的SecurityServletRequestWrapper对象,并重写getSession()和getSession(boolean)方法,让其返回我们自己的session对象,这样就完成了对session的完全控制 。

替换 Servlet 容器的 HttpSession 实现

首选需要编写SecurityServletRequestWrapper类:

public class SecurityServletRequestWrapper extends HttpServletRequestWrapper {
    private static Logger log = LoggerFactory.getLogger(SecurityServletRequestWrapper.class);

    private HttpSession session;

    public SecurityServletRequestWrapper(HttpServletRequest request, HttpSession session) {
        super(request);

        if (null != session) {
            this.session = session;
        }
    }

    @Override
    public HttpSession getSession() {
        log.debug("getSession() invoked!");

        return getSession(true);
    }

    /**
     * 返回自定义的HttpSession实现
     * @param create
     * @return
     */
    @Override
    public HttpSession getSession(boolean create) {
        log.debug("getSession(boolean) invoked!");
        if (create && null == session) {
            log.debug("creating new Session object!");
            session = new NativeHttpSession(getServletContext());
        }

        return session;
    }
}

然后,编写一个filter, 用我们刚刚完成的SecurityHttpServetRequest替换掉doFilter()方法中的第一个参数,代码大致如下:

/**
     * 遍历filters, 依次执行每一个过虑器
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;

            // 将request对象替换成自定义的wrapper对象
            req = new SecurityServletRequestWrapper(req, session);

        chain.doFilter(req, response);

    }

我们必须保证在请求到来时,该过滤器第一个被调用,请求完成后,该过虑器最后被调用。这样我们便可以在chain.doFilter()之前 添加从 Redis 中读取 session的代码,在chain.doFilter()之后添加刷新 session 至 redis 的代码:

@Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;

        // 如果开启了session cluster
        // 执行session cluster相关逻辑
        if (PageProtectionContextListener.SESSION_CLUSTER) {

            // 尝试从存储仓库中查询session
            HttpSession session = sessionDAO.loadSession(getSid(req));

            logger.debug("session loaded, result => {}", session);

            // 将request对象替换成自定义的wrapper对象
            req = new SecurityServletRequestWrapper(req, session);
        }


        chain.doFilter(req, response);

        // 执行session cluster相关逻辑
        if (PageProtectionContextListener.SESSION_CLUSTER) {
            // 刷新session数据

            // 先判断有无session
            HttpSession session = req.getSession(false);
            // 如果没有session, 不做任何处理
            if (null == session) {
                return;
            }

            if (false == session instanceof NativeHttpSession) {
                throw new UnsupportedFilterException("filter " + session.getClass() + " unsupported!");
            }

            NativeHttpSession nativeSession = (NativeHttpSession) session;
            if (nativeSession.isDirty()) {
                logger.debug("flushing session");
                sessionDAO.flushSession(nativeSession);
            }
        }
    }

以上是整体实现思路和关键代码的实现,我们可以在此基础上,根据实际需求添加自己系统需要的功能。

Shiro Session管理实战:从核心原理到集群部署与强制下线实现 会话管理是Web应用安全与用户体验的基石,它通过在服务器端维护用户交互状态来实现身份保持。其核心原理是基于唯一的Session ID在客户端与服务器间建立关联,服务器据此存储用户特定数据。在Java生态中,Apache Shiro框架提供了强大且环境无关的会话管理抽象,其技术价值在于统一了Web与非Web环境下的操作接口,并支持精细化的生命周期控制。这使其在用户认证状态维护、多步骤流程数据暂存以及后台会话治理等应用场景中不可或缺。本文聚焦于Shiro Session的实战操作,深入解析如何通过Session 阅读详情

相关推荐

分布式Session共享:从Redis、JWT到SSO的架构选型与实践

在分布式系统和微服务架构中,用户状态管理是一个基础且关键的技术挑战。其核心原理在于如何让多个服务实例共享用户的认证状态,避免因状态局限在单机内存而导致的重复登录问题。从技术价值看,有效的会话管理方案能直接提升用户体验、保障系统安全,并支撑服务的高可用与水平扩展。常见的应用场景包括电商购物车跨服务同步、多应用统一登录入口等。本文深入探讨了基于Redis的集中存储、JWT无状态令牌、双Token刷新机制以及单点登录(SSO)等主流方案,并结合Spring Session、OAuth 2.0等框架,分析了各方案的

abc20899的专栏 515

Redis进阶学习02---Redis替代Session和Redis缓存

Redis进阶学习02---Redis替代Session基于Session登录流程 本系列参考b站黑马虎哥redis视频编写而成 本系列项目源码将会保存在gitee上面,仓库链接如下: https://gitee.com/DaHuYuXiXi/redis-combat-project 基于Session登录流程 我们先来看一下基于Session实现登录的模板流程是什么样子的: 发送短信验证码 核心逻辑: public Result sendCode(String phone, HttpS

m0_53157173的博客 2916

NVIDIA Jetson Xavier NX刷机+ROS安装+深度学习配置

.NVIDIA Jetson Xavier NX 完整说明流程 V1.0.0 – by Holden Date : 2021-03-19 文章目录.NVIDIA Jetson Xavier NX 完整说明流程1. Jetson Xavier NX简介2. Jetson Xavier NX刷机介绍2.1 工具准备工作2.2 下载镜像以及烧录工具2.3 烧录原生镜像到TF卡2.4 开机启动2.5 组件配置4. 镜像克隆制作5. 镜像重烧写6. NX调控命令 1. Jetson Xavier NX简介 ​ NVI

李老板Holden的博客 7618

session存储的替代方法redis

php默认使用文件存储session,如果并发量大,效率非常低。而redis对高并发的支持非常好,所以,可以使用redis替代文件存储session。 这里,介绍下php的session_set_save_handler 函数的作用和使用方法。该函数定义用户级session保存函数(如打开、关闭、写入等)。原型如下:bool session_set_save_hanler(callback

To be a coder 4037

不止于修改器:用Cheat Engine(CE)的Lua脚本和D3D Hook打造你的游戏辅助界面

本文深入探讨了Cheat Engine(CE)的高级功能,包括Lua脚本自动化和D3D Hook技术,帮助用户从基础内存扫描升级到开发具有专业图形界面的游戏辅助工具。通过实战示例和优化策略,展示了如何创建高效、稳定的游戏辅助系统,并打包为独立训练器。

weixin_28700411的博客 314

05、基于ALV表报实现复选框、全选、取消全选等功能

基于Function ALV实现复选框、全选及取消全选等功能

wo520yl1314的博客 2370

java redis 存session_JavaWeb: Redis存储Session方案

所有支持Servlet规范的容器都自带session管理,于是大多数人都使用HttpSession接口存放状态信息。事实上, servlet的session会使得应用服务器水平扩展变的非常困难。使用Servlet Session时的妥协方案Session Replication这无疑是一种浪费内存的方法,对于5台左右的集群还可以忍受,如果你需要几十甚至上百台集群,这就完全不可行。Session S...

weixin_39640008的博客 1016

3分钟搞懂欧式距离变换(EDT):从暴力算法到Felzenszwalb的演进史

本文系统梳理了欧式距离变换(EDT)从暴力算法到高效线性算法的演进历程。重点解析了光栅扫描算法和Felzenszwalb算法的核心思想与实现,并探讨了其在机器人路径规划中生成欧几里得符号距离场(ESDF)的关键应用,为开发者提供了清晰的算法选型与实战指南。

fern8的博客 976

基于redis的session共享实现

项目上线,闲来无事,把项目里用到的session共享贴出来,因为有多个项目要用到这个功能,所以这个部分功能独立出来了。总得来说,就是自己写了一个拦截器,在拦截器里面把session放进了redis里面,从而实现了session共享。 首先贴出web.xml的配置,和普通拦截器的配置一样: sessionFilter com.dnkx.web.filter.SessionFil

李小拐 YT_FOREVER 2394

宝塔面板 python管理器2.0安装Mrdoc

自从python管理器从1.9升级2.0后,导致原教程不能使用。 故关于2.0新开教程如下。 关于python管理器2.0 最大的区别在于: python管理器2.0不再需要进入虚拟环境,直接在当前环境进行操作,但是需要指定python路径及pip路径。 1、新建mrdoc工程目录,下载源码: 新建目录【mrdoc】,进入mrdoc目录,并在宝塔ssh或或远程ssh中执行 ,下载源码 git clone https://gitee.com/yang_lite/MrDoc.git .

debj031634的专栏 5990

Unity海康视屏对接

通过对接海康SDK,获取视屏流回调。经过解码得到YUV格式的图片,最后通过Shader把YUV数据显示出来。也可以通过Rtsp协议,直接获取视屏流显示。这个貌似Unity中已经有插件支持了,UMP。------2018.4.20using UnityEngine;using System.Collections;using System;using UnityEngine.UI;using Sys...

Witness_K的博客 2028

session一致性-将session存储到redis中

分布式项目通常部署在不同的服务器中,而传统session只存储在本地服务器,并不能实现session的跨域使用。因此实现session一致性通常将sessio存储到redis中,其他服务器获取回话信息直接去redis中获取。spring-session原理就是讲获取session的方式,从tomcate容器获取改为了从redis中获取。 现在spring-session整合redis: pom

Todd的专栏 1万+

Redis实战和核心原理详解(6)使用Spring Session和Redis解决分布式Session跨域共享问题

前言对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash、轮训、根据权重、随机等。不管对于哪一种负载均衡算法,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因此会出现session不同步或者丢失的问题。实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat、Jetty等服务器提供的Session共享

徐刘根的博客 7万+

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

spring-session实现分布式集群session的共享

前言   HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。但是我们把应用搭建成分布式的集群,然后利用LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到多个不同的应用中。那问题来了,如何保证不同的应用能够共享同一份session数据呢?最简单的想法,就是把session数据保存到内存以外的一个统一的地方,例如Mem...

fengbin2005的专栏 297

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

19、springcloud分布式Session之Spring Session

公众号: java乐园 HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。但是把应用搭建成分布式的集群,然后利用F5、LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到多个不同的服务器中。那问题来了,如何保证不同的服务器能够共享同一份session数据呢?最简单的想法,就是把session数据保存到内存以外的一个统一...

天行健,君子以自强不息;地势坤,君子以厚德载物。 4944

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

springboot session超时设置_19、springcloud分布式Session之Spring Session

HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。但是把应用搭建成分布式的集群,然后利用F5、LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到多个不同的服务器中。那问题来了,如何保证不同的服务器能够共享同一份session数据呢?最简单的想法,就是把session数据保存到内存以外的一个统一的地方,例如Memcac...

weixin_39816448的博客 212

深入解析Spring Session分布式会话管理:从HTTP无状态到Redis存储实战

在Web开发中,HTTP协议的无状态特性是构建交互式应用的基础挑战,会话(Session)机制正是为了解决这一问题而诞生。其核心原理是通过服务端生成唯一Session ID并与客户端Cookie关联,从而在多次请求间维持用户状态。随着应用架构演进至分布式与微服务,传统的服务器内存存储方案面临扩展性瓶颈,此时将会话状态外置到共享存储成为关键技术方向。Spring Session作为主流解决方案,通过过滤器拦截并替换原生HttpSession实现,将会话数据持久化至Redis等外部存储,实现了应用实例的无状态化

weixin_33882452的博客 379

servlet如何使用session存储后能否修改_【第一篇】Spring-Session实现Session共享入门教程...

任何一种技术的出现,都是来解决特定的问题的!本篇开始学习Spring-Session相关的一些知识学习整理,让我们开始吧!Spring-Session介绍Spring-Session使用的场景?HttpSession是通过Servlet容器进行创建和管理的,在单机环境中。通过Http请求创建的Session信息是存储在Web服务器内存中,如Tomcat/Jetty。假如当用户通过浏览器访问应用服务...

weixin_39704971的博客 161

在共享dll中使用mfc_在SpringBoot中使用Spring Session解决分布式会话共享问题

作者:简单的土豆前言如果你正在使用Java开发Web应用,想必你对HttpSession非常熟悉,但我们知道HpptSession默认使用内存来管理Session,如果将应用横向扩展将会出现Session共享问题。Spring Session提供了一套创建和管理Servlet HttpSession的方案,以此来解决Session共享的问题,更为重要的是在Spring Boot中使用它极其简单。S...

weixin_39654352的博客 85

【Spring 系列】Spring Session 深度解析

JSR340是Java Servlet 3.1的规范提案,其中定义了大量的api,包括:servlet、servletRequest/HttpServletRequest/HttpServletRequestWrapper、servletResponse/HttpServletResponse/HttpServletResponseWrapper、Filter、Session等,是标准的web容器需要遵循的规约,如tomcat/jetty/weblogic等等。

wenxueliu的博客 1830

Shiro Session管理实战:从原理到集群配置与性能优化

在Java Web开发中,Session管理是维护用户状态、保障应用安全的核心机制。其原理基于服务器端存储用户会话信息,通过Session ID实现客户端与服务器状态的关联,在分布式系统中尤为重要。这项技术的价值在于支撑用户身份保持、访问控制及个性化体验,广泛应用于电商、社交、企业后台等需要登录态管理的场景。本文聚焦Apache Shiro框架的Session管理,深入探讨其架构设计,并结合Redis实现集群Session共享,解决分布式环境下的状态同步问题。文中详细解析了Session固定攻击防御、序列化

weixin_30291791的博客 331

共享Session问题

1.共享Session问题 HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。而如果我们把web服务器搭建成分布式的集群,然后利用LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到两个不同的web站点中去。那么问题就来了,如何保证不同的web站点能够共享同一份session数据呢?  最简单的想法就是把ses

新一难的博客 764

Spring-Session揭秘(一)

在开始spring-session揭秘之前,先做下热脑(活动活动脑子)运动。为什么要spring-session比较traditional-session方案和spring-session方案JSR340规范与spring-session的透明继承spring-session提供集群环境下HttpSession的透明集成。spring-session的优势在于开箱即用,具有较强的设计模式。

sdujava2011 237

使用Spring Session和Redis解决分布式Session跨域共享问题

http://blog.youkuaiyun.com/xlgen157387/article/details/57406162前言对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash、轮训、根据权重、随机等。不管对于哪一种负载均衡算法,由于Nginx对不同的请...

liyanlei的专栏 291
上一篇: 集群环境下使用Shiro的技术方案(With Redis)
下一篇: Intellij Idea下运行Spring Boot关于provided依赖不加入classpath的bug与解决方案
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值