34

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

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

我使用 jstl<c:url..>标签来创建所有 URL。

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

4

7 回答 7

41

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

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

于 2009-06-25T19:09:26.587 回答
27

正如skaffman 的回答中所解释的,它不是一个错误。它是一种预期的行为

在您的问题中, 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 感觉就像是 hack,因为您需要更改默认行为。但这一切都取决于您需要和想要实现的目标。

于 2012-06-21T09:09:37.637 回答
20

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

<session-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>
于 2012-02-08T17:13:46.160 回答
7

这是一种令人讨厌的解决方法,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 模式。

于 2010-10-25T22:46:38.053 回答
2

如果您有一个所有页面都使用的通用包装器页面(对我来说是 common.inc),您可以添加session="false"到您的<%@ 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"输出变量,这将删除 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]
于 2015-02-17T21:26:25.133 回答
1

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

于 2010-10-25T19:33:15.927 回答
0

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

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

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

于 2009-06-25T19:32:50.957 回答