我遇到了一些奇怪的错误:当我第一次在某些浏览器中打开页面时,所有引用都有 jsessionid 参数(如
<a href="/articles?name=art&jsessionid=5as45df4as5df"..>
)。
当我按 F5 或通过任何其他方式刷新页面时,所有这些内容都会消失,一切正常,直到我关闭浏览器(并且所有选项卡也应该关闭)。当我再次打开它时,我看到这个奇怪的 jsessionid 参数。
我使用 jstl
<c:url..>
标签来创建所有 URL。
我前一段时间读过,如果cookie被禁用,jsessionid是cookie的替代品,但是启用cookie并且我实际上不使用cookie。
这不是错误,而是设计使然。创建新会话时,服务器不确定客户端是否支持 cookie,因此它会在 URL 上生成 cookie 和 jsessionid。当客户端第二次返回并呈现 cookie 时,服务器知道 jsessionid 不是必需的,并在会话的其余部分中删除它。 如果客户端返回没有cookie,那么服务器需要继续使用jsessionid重写。
您可能没有显式使用 cookie,但您确实隐式拥有一个会话,并且容器需要跟踪该会话。
在 Tomcat 7 或任何符合 servlet 规范 v3 的服务器上,您可以通过将以下内容添加到应用程序的 web.xml 来禁用 URL 中的 jsessionid
<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
这里有一个
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 模式。
如果您有一个所有页面都使用的通用包装页面(对我来说是 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]
一种解决方法是不使用
<c:url>
,而是使用 ${request.contextPath}/path
不幸的是,我发现解决此问题的唯一方法是向您的应用程序添加一个过滤器,该过滤器将删除 jsessionid 参数。如果您正在创建一个公共网站并希望搜索引擎为您的页面建立索引,那么这尤其令人烦恼。
我不相信tomcat(如果您正在使用的话)可以配置为不将其添加到您的网址中。但我不能说其他服务器。
但是,请注意,如果您创建了过滤器,然后需要会话管理并且用户关闭了 cookie,您将会遇到问题。
如果您的项目使用 Spring Boot 那么您可以添加
server.servlet.session.tracking-modes=cookie
在 application.properties 文件中防止在 url 中暴露 jsession id