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

2024-04-21 05:18

本文主要是介绍替换Servlet容器的HttpSession实现集群中Session共享(With 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;}}@Overridepublic HttpSession getSession() {log.debug("getSession() invoked!");return getSession(true);}/*** 返回自定义的HttpSession实现* @param create* @return*/@Overridepublic 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, 依次执行每一个过虑器*/@Overridepublic 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 的代码:

@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;// 如果开启了session cluster// 执行session cluster相关逻辑if (PageProtectionContextListener.SESSION_CLUSTER) {// 尝试从存储仓库中查询sessionHttpSession 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数据// 先判断有无sessionHttpSession 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);}}}

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

这篇关于替换Servlet容器的HttpSession实现集群中Session共享(With Redis)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/922234

相关文章

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

HDFS—集群扩容及缩容

白名单:表示在白名单的主机IP地址可以,用来存储数据。 配置白名单步骤如下: 1)在NameNode节点的/opt/module/hadoop-3.1.4/etc/hadoop目录下分别创建whitelist 和blacklist文件 (1)创建白名单 [lytfly@hadoop102 hadoop]$ vim whitelist 在whitelist中添加如下主机名称,假如集群正常工作的节

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]