我有一些奇怪的错误:当我第一次在某个浏览器中打开页面时,所有引用都有jsessionid参数(如<a href="/articles?name=art&jsessionid=5as45df4as5df"..>
)。
当我按F5或以任何其他方式刷新页面时,所有内容都消失了,一切正常,直到我关闭浏览器(并且所有选项卡也应该关闭)。当我再次打开它时,我看到了这个奇怪的jsessionid参数。
我使用jstl <c:url..>
标记来创建所有网址。
我前段时间读过,如果禁用cookie,jsessionid可以替代cookie,但是启用了cookie,我实际上不使用cookie。
答案 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