在jstl <c:url ..> tag </c:url ..>生成的所有URL中都出现了jsessionid

时间:2009-06-25 19:07:13

标签: jsp jstl jsessionid

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

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

我使用jstl <c:url..>标记来创建所有网址。

我前段时间读过,如果禁用cookie,jsessionid可以替代cookie,但是启用了cookie,我实际上不使用cookie。

7 个答案:

答案 0 :(得分:39)

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

您可能没有明确使用Cookie,但您隐式拥有会话,而容器需要跟踪该会话。

答案 1 :(得分:26)

skaffman's answer中所述, 不是错误。它是一种预期的行为

在你的问题中,jsessionid作为参数附加,但情况并非如此 使用
<c:url value="/"/>
将产生如下内容:/some/;jsessionid=E85FAC04E331FFCA55549B10B7C7A4FA
所以使用
<link href="<c:url value="/"/>stylesheets/style.css" rel="stylesheet" type="text/css"/>
会产生 /some/;jsessionid=E85FAC04E331FFCA55549B10B7C7A4FAstylesheets/style.css
,所以你的服务器找不到可用的资源。

我找到的最佳解决方法是使用${pageContext.request.contextPath}代替<c:url value="/"/> 。所以在前面的例子中,你会有 <link href="${pageContext.request.contextPath}/stylesheets/style.css" rel="stylesheet" type="text/css"/>
这将产生
/some/stylesheets/style.css

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

答案 2 :(得分:14)

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

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

答案 3 :(得分:5)

这是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模式。

答案 4 :(得分:2)

如果你有一个所有页面都使用的公共包装页面(对我而言,它是common.inc) 您可以将session="false"添加到<%@ page以删除会话ID。

示例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"输出变量,这将删除sessionid。

示例:

<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]

答案 5 :(得分:0)

不幸的是,我找到的唯一方法是在你的应用程序中添加一个过滤器来删除jsessionid参数。如果你正在创建一个公共网站并希望搜索引擎为你的网页编制索引,那就特别烦人了。

我不相信tomcat(如果那是你正在使用的)可以配置为不将它添加到你的网址。我不能说其他服务器。

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

答案 6 :(得分:0)

一种解决方法是不使用<c:url>,而是使用${request.contextPath}/path