关于JSESSIONID

好久没写博客了,一直没什么好写的,最近碰到JSESSIONID这个问题,网上的说法有点模糊,特别是什么时候会出现URL重写这个问题,有些说客户端禁用Cookie,有些说第一次访问,这里总结一下

JSESSIONID是什么

老实说一开始看到这个有点懵,写Java这么久没看过这东西。

首先,JSESSIONID是一个Cookie,Servlet容器(tomcat,jetty)用来记录用户session。

什么时候种下JSESSIONID

创建会话时,即调用request.getSession()的时候,关于getSession就不说了。补充几点是,访问html是不会创建session的,JSP页面默认是会创建session的,可以在JSP页面里面关掉自动创建session

URL重写

服务端在内存里创建session,需要种Cookie,除了在request header里面设置Set-Cookie以外,tomcat等容器有一个URL重写机制。这个机制是客户端Cookie不可用时的一个兜底策略,通过在URL后面加上;jsessionid=xxx来传递session id,这样即使Cookie不可用时,也可以保证session的可用性,但是session暴露在URL里,本身是不安全的,到这里基本网上说法都是一致的

但是最关键的问题,tomcat怎么知道客户端Cookie不可用。我在idea导入tomcat的源码调试跟踪,不同版本有些出入,大致应该还是一样的

tomcat有一个org.apache.catalina.connector.Response是Response的落地类,有两个方法会进行URL重写,分别是encodeRedirectURLencodeURLencodeRedirectURL是重定向时会被调用,encodeURL貌似是手动调用,所以默认情况,重定向时才会出现URL重写。两个方法代码类似,下面只关注encodeRedirectURL

/**
     * Encode the session identifier associated with this response
     * into the specified redirect URL, if necessary.
     *
     * @param url URL to be encoded
     * @return <code>true</code> if the URL was encoded
     */
    @Override
    public String encodeRedirectURL(String url) {

        if (isEncodeable(toAbsolute(url))) {
            return (toEncoded(url, request.getSessionInternal().getIdInternal()));
        } else {
            return (url);
        }

    }

方法注释写得很清楚了,如果有必要的话,把session id塞到重定向的URL里面。再看一下isEncodeable方法,关键地方我加了中文注释

/**
     * Return <code>true</code> if the specified URL should be encoded with
     * a session identifier.  This will be true if all of the following
     * conditions are met:
     * <ul>
     * <li>The request we are responding to asked for a valid session
     * <li>The requested session ID was not received via a cookie
     * <li>The specified URL points back to somewhere within the web
     *     application that is responding to this request
     * </ul>
     *
     * @param location Absolute URL to be validated
     * @return <code>true</code> if the URL should be encoded
     */
    protected boolean isEncodeable(final String location) {

        if (location == null) {
            return false;
        }

        // Is this an intra-document reference?
        if (location.startsWith("#")) {
            return false;
        }

        // Are we in a valid session that is not using cookies?
        final Request hreq = request;
        final Session session = hreq.getSessionInternal(false);
        if (session == null) {
            return false;
        }
        //这里其实就是网上说的客户端禁用Cookie
        if (hreq.isRequestedSessionIdFromCookie()) {
            return false;
        }

        // Is URL encoding permitted
        // servlet3.0后可以在项目web.xml里关掉URL重写,对应tomat7之后
        if (!hreq.getServletContext().getEffectiveSessionTrackingModes().
                contains(SessionTrackingMode.URL)) {
            return false;
        }

        if (SecurityUtil.isPackageProtectionEnabled()) {
            return (
                AccessController.doPrivileged(new PrivilegedAction<Boolean>() {

                @Override
                public Boolean run(){
                    return Boolean.valueOf(doIsEncodeable(hreq, session, location));
                }
            })).booleanValue();
        } else {
            //这个方法会重写URL
            return doIsEncodeable(hreq, session, location);
        }
    }

其中调用Request对象的isRequestedSessionIdFromCookie判断客户端Cookie是否可用,里面逻辑也很简单,就是读取request里面有没有传JSESSIONID这个Cookie。所以网上有些人说第一次访问,其实只要客户端没有传JSESSIONID,tomcat都假定Cookie不可用

参考资料:
什么是JSESSIONID,这个说得比较清楚
关掉URL重写

推荐阅读更多精彩内容

  • 目录Cookie机制什么是CookieCookie的不可跨域名性Unicode编码:保存中文BASE64编码:保存...
    Tomatoro阅读 16,322评论 7 186
  • 会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Se...
    chinariver阅读 5,278评论 1 49
  • Session机制 除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session...
    薛晨阅读 6,481评论 4 34
  • 走在十字的街口,或徘徊,或等待。风,一再一再的吹动着你的脸颊,从容自若是你我共同的选择。 路,总是要走的。来到了九...
    米澜盛若阅读 134评论 0 0
  • 你又不会写作文,咋教学生? 正牙每天都要去下来,有啥用,不如那种一直勒着的。 练字写那么慢,翻来覆去就那几个字,有...
    天添美_再出发阅读 247评论 0 0
  • 2018-3-27 晴 星期二 亲子日记第185篇 今天的天气非常炎热,大街上的美女帅哥都穿上了漂亮的背心、裙裙,...
    敏文妈咪阅读 194评论 0 4
  • 今天,y打电话来,问我病情如何。我很开心。 于是,跟他絮叨说刚刚想打电话给他,可一想他在上班,就没有打,没想到他碰...
    依依_2323阅读 104评论 0 0