图标丢失,URL带上jsessionid是什么鬼?

最近在折腾一个旧系统,从IE浏览器搬到谷歌浏览器。这当然是没法直接搬的,主要是依赖了一个谷歌插件IETab,对部分无法兼容的Struts2/JSP页面菜单采用IETab打开,遇到了一个奇怪事情,页面上的有些图标显示不出来,下面记录一下主要的定位过程和原因分析。


一开始的时候,我就注意到有些菜单里边的图标实现不了,但也不是必现的,有些菜单就是可以的,所以没留意这个问题。后来其他人也发现了,才发现只有在IETab打开某些菜单才会。


看来一下请求的路径,发现是图标是404,调用路径是a.gif;jessionid=xxxxx的格式。的确这种路径会在当前nginx配置下被拦掉,但我点一下查询,页面刷一刷图标就正常了。还好是搞过JSP/Servlet的,我意识到这个机制是采用URL重写来传递会话标识,在Cookie会话标识不存在的情况下会有这种情况。


了解到这点,后面也很快理清楚整个过程了。这个系统外层路径是/a,通过iframe打开真实菜单路径/b,首先/b这里打开的是一个JSP页面,这个图标是在一个JSP标签上生成的,生成URL的时候调用了response.encodeURL,这就可能出现URL重写情况。另外,IEtab免费版不支持打开IE时传递Cookie信息,虽然我们用来一定的手段把Cookie传递到/a了,但是/b的会话没有带过来,所以打开/b的同时生成图标路径的时候,就出现了URL重写。


以前不存在会话带不过去的问题,这也能解释,为什么换成IETab之后这个问题变得很明显了。


这是一个旧应用,会话是必须的,配置也不能随便动,最终打了个小补丁:在打开/a的时候,先在页面提前访问一下/b的一个简单路径,这样/b的会话标识有了,再打开菜单就正常显示图标了。


虽然现在已经不流行JSP了,但JSP还是相当强大的。定位过程顺手翻了一下encodeURL在tomcat的具体实现,顿时又有点怀念了。


源码跟踪记录


主要源码在org.apache.catalina.connector.Response。


@Override
public String encodeURL(String url) {
    ...
    if (isEncodeable(absolute)) {
        ...
        return toEncoded(url, request.getSessionInternal().getIdInternal());
    }
    ...
}


核心方法就逻辑就在这两段,isEncodeable判断要不要对URL编码,toEncoded对URL进行编码。


protected boolean isEncodeable(final String location) {
    ...
    // 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;
    }
    if (hreq.isRequestedSessionIdFromCookie()) {
        return false;
    }

    // Is URL encoding permitted
    if (!hreq.getServletContext().getEffectiveSessionTrackingModes().
            contains(SessionTrackingMode.URL)) {
        return false;
    }
    ...
}


判断要不要编码也很简单,判断有没有会话,如果有会话判断在Cookie中有没有会话ID。如果没有会话ID,看支不支持URL会话跟踪,只有支持这个特性的情况下才需要考虑URL编码。


会话跟踪特性介绍:



  • https://stackoverflow.com/questions/16262285/set-tracking-mode-to-cookie-to-remove-appended-session-id-without-using-web-xml
  • https://www.logicbig.com/tutorials/java-ee-tutorial/java-servlet/session-tracking-mode.html


protected String toEncoded(String url, String sessionId) {
    ...
    StringBuilder sb = new StringBuilder(path);
    if( sb.length() > 0 ) { // jsessionid can't be first.
        sb.append(';');
        sb.append(SessionConfig.getSessionUriParamName(
                request.getContext()));
        sb.append('=');
        sb.append(sessionId);
    }
    ...
}


编码的方式就是在路径后面加上在加上;jessionid=xxxx的路径。


原文始发于微信公众号(程序员的胡思乱想):图标丢失,URL带上jsessionid是什么鬼?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/22606.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!