Tomcat 中的Session与Cookie

1.问题引入

今天在梳理系统的时,查看系统中的session共享的实现方式,目前主流的session共享采用spring-session 与 redis的解决方案,无奈系统架构还在使用struts2 等老旧的框架,发现原来的session共享的思路与spring-session很是相似,都是通过一个filter过滤器并且自己封装一个request实现HttpServletRequestWrapper ,并重写里面的getSession方法。至于具体实现不多说,由于http 这种无状态的协议,服务端保持会话需要同客户端配合。原理就是

获取session时 会有一个session的标志ID 该id 一般通过写cookie的方式 写入到客户端浏览器中。

tomcat中写cookie的name 一般默认为  JSESSIONID ,写入cookie 后 浏览器中可查看该cookie


会有一个路径 /weixin

然后客户端向服务端发送请求时会携带该cookie信息。

然后服务端根据cookie中的JSESSIONID的值从redis中获取存储的session信息。

那么问题来了  

这个路径 /weixin  和 /weixin/ 一样吗

显然不一样 

调试过程中 由于 前面提到的filter 没有拦截一些url 导致,一些请求产生了基于tomcat自己的session,没有从redis中获取。但是查看浏览器发现 JSESSIONID 这个cookie的存储路径 竟然为 /weixin/

然而其他拦截到的url 存的路径为 /weixin (开发人员自己设置的,获取的为contextpath)

也就是开发人员自己设置的 路径与 tomcat 自己设置的路径 不一样。这时调试环境的tomcat版本为8.0.X

我换成了 tomcat8.5.37时  cookie的路径竟然又变回了  /weixin

什么情况这是 。。。。。。。。

2.问题定位

为了一探究竟 我自己查看了 tomcat 设置cookie的路径的地方。

在 ApplicationSessionCookieConfig.java 类中 创建cookie的地方

/**

    * Creates a new session cookie for the given session ID

    *

    * @param context    The Context for the web application

    * @param sessionId  The ID of the session for which the cookie will be

    *                    created

    * @param secure      Should session cookie be configured as secure

    * @return the cookie for the session

    */

    public static Cookie createSessionCookie(Context context,

            String sessionId, boolean secure) {

        SessionCookieConfig scc =

            context.getServletContext().getSessionCookieConfig();

        // NOTE: The priority order for session cookie configuration is:

        //      1. Context level configuration

        //      2. Values from SessionCookieConfig

        //      3. Defaults

        Cookie cookie = new Cookie(

                SessionConfig.getSessionCookieName(context), sessionId);

        // Just apply the defaults.

        cookie.setMaxAge(scc.getMaxAge());

        cookie.setComment(scc.getComment());

        if (context.getSessionCookieDomain() == null) {

            // Avoid possible NPE

            if (scc.getDomain() != null) {

                cookie.setDomain(scc.getDomain());

            }

        } else {

            cookie.setDomain(context.getSessionCookieDomain());

        }

        // Always set secure if the request is secure

        if (scc.isSecure() || secure) {

            cookie.setSecure(true);

        }

        // Always set httpOnly if the context is configured for that

        if (scc.isHttpOnly() || context.getUseHttpOnly()) {

            cookie.setHttpOnly(true);

        }

        cookie.setPath(SessionConfig.getSessionCookiePath(context));

        return cookie;

    }


发现是从SessionConfig.java  获取的path ,然后继续贴代码

public static String getSessionCookiePath(Context context) {

        SessionCookieConfig scc = context.getServletContext().getSessionCookieConfig();

        String contextPath = context.getSessionCookiePath();

        if (contextPath == null || contextPath.length() == 0) {

            contextPath = scc.getPath();

        }

        if (contextPath == null || contextPath.length() == 0) {

            contextPath = context.getEncodedPath();

        }

        if (context.getSessionCookiePathUsesTrailingSlash()) {

            // Handle special case of ROOT context where cookies require a path of

            // '/' but the servlet spec uses an empty string

            // Also ensure the cookies for a context with a path of /foo don't get

            // sent for requests with a path of /foobar

            if (!contextPath.endsWith("/")) {

                contextPath = contextPath + "/";

            }

        } else {

            // Only handle special case of ROOT context where cookies require a

            // path of '/' but the servlet spec uses an empty string

            if (contextPath.length() == 0) {

                contextPath = "/";

            }

        }

        return contextPath;

    }

发现 其根据 SessionCookiePathUsesTrailingSlash 配置 来确定是否在  contextPath 后面加 “/” 

难道问题出在 这个属性的设置上?

然后我就查看tomcat的更新日志 果然查到了呢 哈哈哈哈哈哈

https://tomcat.apache.org/tomcat-8.5-doc/changelog.html

在8.5.4的版本中  有更新的说明如下 

Change the default of the sessionCookiePathUsesTrailingSlash attribute of the Context element to false since the problems caused when a Servlet is mapped to /* are more significant than the security risk of not enabling this option by default. (markt)

也就是 之前这个属性为 true 之后版本默认值改成了false 

所以 cookie的路径 返回  一个 为 /weixin/   一个为/weixin

至于为什么要修改呢

检索到这么一篇文章

http://tomcat.10.x6.nabble.com/Problems-with-default-for-sessionCookiePathUsesTrailingSlash-td5051868.html

从以上文章中可以学到  cookie 的path的作用呢 。

你可能感兴趣的:(Tomcat 中的Session与Cookie)