jsessionid 出现在由 jstl <c:url..> 标签生成的所有 url

Posted

技术标签:

【中文标题】jsessionid 出现在由 jstl <c:url..> 标签生成的所有 url【英文标题】:jsessionid is occurred in all urls which are generated by jstl <c:url..> tag 【发布时间】:2010-11-05 22:48:35 【问题描述】:

我遇到了一些奇怪的错误:当我第一次在某些浏览器中打开页面时,所有引用都有 jsessionid 参数(如&lt;a href="/articles?name=art&amp;jsessionid=5as45df4as5df"..&gt;)。

当我按 F5 或以任何其他方式刷新页面时,所有内容都会消失,并且一切正常,直到我关闭浏览器(并且所有选项卡也应该关闭)。当我再次打开它时,我看到了这个奇怪的 jsessionid 参数。

我使用 jstl &lt;c:url..&gt; 标签来创建所有 URL。

我前段时间读到,如果禁用 cookie,则 jsessionid 是 cookie 的替代品,但启用了 cookie 而我实际上不使用 cookie。

【问题讨论】:

您在此处编写的格式 不准确。请参阅我的回答 ***.com/a/11134953/521754 以获得正确的格式。干杯! 【参考方案1】:

正如skaffman's answer 中所解释的,这不是错误。这是预期的行为

在您的问题中,jsessionid 作为参数附加,但事实并非如此。 使用&lt;c:url value="/"/&gt; 将生成如下内容:/some/;jsessionid=E85FAC04E331FFCA55549B10B7C7A4FA. 所以使用&lt;link href="&lt;c:url value="/"/&gt;stylesheets/style.css" rel="stylesheet" type="text/css"/&gt; 将生成/some/;jsessionid=E85FAC04E331FFCA55549B10B7C7A4FAstylesheets/style.css ,因此您的服务器找不到可用的资源。

我发现的最佳解决方法是使用$pageContext.request.contextPath 而不是&lt;c:url value="/"/&gt;。所以在前面的例子中,你会有&lt;link href="$pageContext.request.contextPath/stylesheets/style.css" rel="stylesheet" type="text/css"/&gt; 这将生成/some/stylesheets/style.css.

此解决方案独立于容器(而符合 servlet 规范 v3 的容器 - 如 Tomcat - 解决方案不是)。过滤响应 url 感觉就像是 hack,因为您需要更改默认行为。但这一切都取决于您需要和想要实现的目标。

【讨论】:

【参考方案2】:

如果您有一个所有页面都使用的通用包装页面(对我来说是 common.inc) 您可以将 session="false" 添加到您的 &lt;%@ page 以删除 sessionid。

例如common.inc

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" session="false" trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="ab" tagdir="/WEB-INF/tags" %>

<c:set var="contextPath" scope="request" value="$ pageContext.request.contextPath " />
<c:set var="assetPath" scope="request" value="/assets" />
<c:set var="debugEnabled" scope="request" value="$ applicationDebugProperties.debugEnabled " />

或者.. 将c:url 的值设置为变量并使用c:out escapeXml="false" 输出变量,这将删除会话ID。

例子:

<c:url value=$url var="image"/>
<c:out var=$image escapeXml="false"/>

或者,您可以将其添加到您的 Apache 配置中以截断 sessionid。

ReWriteRule ^/(\w+);jsessionid=\w+$ /$1 [L,R=301]
ReWriteRule ^/(\w+\.go);jsessionid=\w+$ /$1 [L,R=301]

【讨论】:

【参考方案3】:

在 Tomcat 7 或任何符合 servlet 规范 v3 的服务器上,您可以通过在应用程序的 web.xml 中添加以下内容来禁用 URL 中的 jsessionid

<session-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>

【讨论】:

c:url 仍然可以导致附加 jsessionid,即使使用此设置。 tomcat7/servlet3 适合我,我正在使用嵌入式码头。【参考方案4】:

这是一个讨厌的解决方法,类似于 Filter,这样只要客户端支持 cookie,您就永远不会在 URL 中看到 jsessionid。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    HttpSession session = req.getSession();

    if (session.isNew()) 
        // New session? OK, redirect to encoded URL with jsessionid in it (and implicitly also set cookie).
        res.sendRedirect(res.encodeRedirectURL(req.getRequestURI()));
        return;
     else if (session.getAttribute("verified") == null) 
        // Session has not been verified yet? OK, mark it verified so that we don't need to repeat this.
        session.setAttribute("verified", true);
        if (req.isRequestedSessionIdFromCookie()) 
            // Supports cookies? OK, redirect to unencoded URL to get rid of jsessionid in URL.
            res.sendRedirect(req.getRequestURI().split(";")[0]);
            return;
        
    

    chain.doFilter(request, response);

将其映射到 /* 或任何需要会话管理的 URL 模式。

【讨论】:

嗨 BalusC,感谢您的回答!我目前不做网络开发,但我会在我的一个有这个问题的旧项目上尝试你的解决方案。您能否解释一下(或提供相应链接)编码/未编码 URL 的概念?为什么这很重要?我缺乏了解它的另一件事是会话的“已验证”属性。通常由谁以及何时设置? Skaffman 已经回答了 URL 中对 jsessionid 的需求。一旦验证了 cookie 支持,verified 属性就可以防止过滤器在无限循环中运行。您可以随意将其重命名为其他名称。【参考方案5】:

一种解决方法是不使用&lt;c:url&gt;,而是使用$request.contextPath/path

【讨论】:

只是为了澄清这一点——应该是$pageContext.request.contextPath【参考方案6】:

不幸的是,我发现的唯一方法是向您的应用程序添加一个过滤器,该过滤器将去除 jsessionid 参数。如果您正在创建一个公共网站并希望搜索引擎为您的网页编制索引,这尤其令人讨厌。

我不相信可以将 tomcat(如果您正在使用的话)配置为不将其添加到您的 url。不过我不能说其他服务器。

但是,请注意,如果您确实创建了过滤器,然后您需要会话管理并且用户关闭了 cookie,您将会遇到问题。

【讨论】:

有趣的是,他的示例在 URL 中将 jsessionid 作为参数。我没见过以前的。 Tomcat 将其作为 URL 的后缀(例如 my/path;jsessionid=...&x=y),我认为这是 servlet 规范所要求的。 其实我弄错了,不是参数而是我当时忘记了具体格式 Tomcat 7 可用于此。 Tomcat 6.0.30 会有这个特性。【参考方案7】:

这不是错误,这是设计使然。创建新会话时,服务器不确定客户端是否支持 cookie,因此它会生成一个 cookie 以及 URL 上的 jsessionid。当客户端第二次返回并呈现 cookie 时,服务器知道 jsessionid 不是必需的,并在会话的其余部分将其丢弃。如果客户端返回没有cookie,那么服务端需要继续使用jsessionid重写。

您可能没有明确使用 cookie,但您确实有一个会话,并且容器需要跟踪该会话。

【讨论】:

很好,但我所有的 CSS 看起来都像“link rel=".." href="/mysite/css/styles.css?jsessionid=as2dfs4df"。我可以关闭这个默认行为还是这将是一个不好的做法,我应该修复我的 CSS 加载? 这将取决于您在哪个容器中运行 但是,一般来说,在 url 中使用 JSESSIONID 进行 URL 重写并不是非常非常不安全的。在 TLS/HTTPS 连接上,cookie 也会被加密,因此 JSESSIONID 不会被窃听。但即使在 url 中带有 JESSIONID 的 HTTPS 连接上,JSESSIONID 也完全暴露在窃听中。这似乎是一个严重的安全问题。为什么即使禁用了 cookie 也会采用这种方法。

以上是关于jsessionid 出现在由 jstl <c:url..> 标签生成的所有 url的主要内容,如果未能解决你的问题,请参考以下文章

spring mvc默认index.jsp页面绑定请求出现的jsessionid=xxx路径的问题

spring mvc默认index.jsp页面绑定请求出现的jsessionid=xxx路径的问题

java jsessionid啥时候 生成的

什么是jstl表达式,怎么应用

JSP自定义标签JSTL标签库

jsessionid说明