当前位置:首页 > 资讯 > info5 > 正文

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

发表于: 2016-03-11   作者:tracker_w   来源:转载   浏览:
摘要: 本文是我个人在开发web-security安全框架中使用的方案。在WebServer集群环境中需要实现session共享,一个很好的方法就是将session数据存放至Redis中。我打算在自己的安全框架中集成此功能,只需要几行配置就能自动让你的web项目集成redissession共享功能。实现思路为:将Servlet容器的HttpSession实现替换成自己的实现,如RedisHttpSessi

本文是我个人在开发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);
            }
        }
    }

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

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

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
一、存储 前段时间,我花了不少时间来寻求一种方法,把新开发的代码推送到到生产系统中部署,生产系
Nginx 作为目前最流行的开源反向代理HTTP Server,用于实现资源缓存、web server负载均衡等功能,由
  上一篇介绍了一些redis的安装及使用步骤,本篇开始将介绍redis的实际应用场景,先从最常见的sess
  上一篇介绍了如何使用nginx+iis部署一个简单的分布式系统,文章结尾留下了几个问题,其中一个是
近期在做一套集群的实现,实现的方案是在Linux下完成对Apache + Tomcat 负载均衡的功能。 上述功能
在测试虚拟机centos6.5 IP地址:192.168.20.31 中安装tomcat8,单机集群,需要安装两个tomcat 然后
一、Nginx安装   详见前文:http://www.cnblogs.com/yixiwenwen/p/3574097.html 二、memcached安
一、Nginx安装   详见前文:http://www.cnblogs.com/yixiwenwen/p/3574097.html 二、memcached安
转载自:http://alvin1.blog.51cto.com/6223380/1252619 一、Nginx部分 1.1、Nginx介绍 Nginx是俄罗
一、Nginx安装   详见前文:http://www.cnblogs.com/yixiwenwen/p/3574097.html 二、memcached安
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号