我想完全消除HttpSession - 我可以在web.xml中这样做吗?我确信有容器特定的方法可以做到这一点(当我进行谷歌搜索时,这是搜索结果的主要内容)。
P.S。这是一个坏主意吗?在我真正需要它之前,我更喜欢完全禁用它们。
答案 0 :(得分:72)
我想完全消除HttpSession
你不能完全禁用它。您需要做的只是不,以便在您的网络应用程序代码中的任何位置request.getSession()
或request.getSession(true)
处理它,并确保您的JSP不会隐式通过设置<%@page session="false"%>
。
如果您的主要问题实际上是禁用在HttpSession
幕后使用的cookie,那么您可以在Java EE 5 / Servlet 2.5中仅在特定于服务器的webapp配置中执行此操作。例如,在Tomcat中,您可以在cookies
元素中将false
属性设置为<Context>
。
<Context cookies="false">
另见Tomcat specific documentation。这样,会话将不会保留在后续的URL重写请求中 - 只要您出于某种原因从请求中获取它时。毕竟,如果你不需要它,只是不抓住它,那么根本不会创建/保留它。
或者,如果您已经使用Java EE 6 / Servlet 3.0或更高版本,并且真的想通过web.xml
进行,那么您可以使用<cookie-config>
中的新web.xml
元素如下所示,将最大年龄归零:
<session-config>
<session-timeout>1</session-timeout>
<cookie-config>
<max-age>0</max-age>
</cookie-config>
</session-config>
如果您想在自己的网络应用程序中进行硬编码,以便getSession()
永远不会返回HttpSession
(或“空”HttpSession
),那么您需要创建一个监听过滤器url-pattern
/*
HttpServletRequest
将getSession()
替换为HttpServletRequestWrapper
实现,该实现返回所有null
方法HttpSession
或虚拟自定义{{ 1}}实现什么都不做,甚至抛出UnsupportedOperationException
。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) request) {
@Override
public HttpSession getSession() {
return null;
}
@Override
public HttpSession getSession(boolean create) {
return null;
}
}, response);
}
P.S。这是一个坏主意吗?在我真正需要它之前,我更喜欢完全禁用它。
如果您不需要它们,请不要使用它们。就这样。真的:)
答案 1 :(得分:7)
如果您正在构建无状态高负载应用程序,则可以禁用使用cookie进行会话跟踪(非侵入式,可能与容器无关):
<session-config>
<tracking-mode>URL</tracking-mode>
</session-config>
要强制执行此体系结构决策,请执行以下操作:
public class PreventSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
throw new IllegalStateException("Session use is forbidden");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
throw new IllegalStateException("Session use is forbidden");
}
}
并将其添加到web.xml并修复失败的地方,但该例外:
<listener>
<listener-class>com.ideas.bucketlist.web.PreventSessionListener</listener-class>
</listener>
答案 2 :(得分:4)
我使用以下方法为我的RESTful应用程序删除任何无意中的会话cookie,使其不会被创建和。
<session-config>
<session-timeout>1</session-timeout>
<cookie-config>
<max-age>0</max-age>
</cookie-config>
</session-config>
但是,这并没有完全关闭HttpSessions。应用程序仍可能无意中创建会话,即使它在一分钟内消失,流氓客户端也可能忽略cookie的max-age请求。
此方法的优点是您无需更改应用程序,只需web.xml
。我建议您创建一个HttpSessionListener
,它将在创建或销毁会话时记录,以便您可以跟踪它何时发生。
答案 3 :(得分:2)
我想完全消除HttpSession - 我可以在web.xml中这样做吗?我确信有容器特定的方法可以做到这一点
我不这么认为。禁用HttpSession
将违反Servlet规范,该规范声明HttpServletRequest#getSession
应返回会话或创建会话。所以我不希望Java EE容器提供这样的配置选项(这会使它不兼容)。
这是个坏主意吗?在我真正需要它之前,我更喜欢完全禁用它们。
好吧,我真的不明白,如果你不想使用它,就不要在会话中放任何东西。现在,如果您确实希望阻止使用会话,则可以使用Filter
将请求替换为HttpServletRequestWrapper
覆盖getSession()
的实现。但我不会浪费时间实现这个:)
更新:我的初步建议并非最佳,“正确”( cough )的方式是替换请求。
答案 4 :(得分:2)
您可以使用URL重写过滤器(例如tuckey rewrite filter)重写URL,而不是禁用。这将为Google提供友好的结果,但仍允许基于Cookie的会话处理。
但是,您可能应该为所有响应禁用它,因为它比不友好的搜索引擎更糟糕。它公开了可用于certain security exploits的会话ID。
对于Tuckey过滤器<outbound-rule encodefirst="true">
<name>Strip URL Session ID's</name>
<from>^(.*?)(?:\;jsessionid=[^\?#]*)?(\?[^#]*)?(#.*)?$</from>
<to>$1$2$3</to>
</outbound-rule>
答案 5 :(得分:2)
在使用Java Config的Spring Security 3中,您可以使用HttpSecurity.sessionManagement():
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
Xml看起来像这样;
<http create-session="stateless">
<!-- config -->
</http>
顺便说一下,NEVER和STATELESS之间的区别
永远不会:Spring Security永远不会创建HttpSession,但会使用 HttpSession如果它已经存在
STATELESS:Spring Security永远不会创建一个HttpSession,它会 永远不要用它来获取SecurityContext
答案 6 :(得分:2)
从Servlet 3.0开始,您可以通过将这样的代码添加到contextInitialized
的{{1}}方法中来使Servlet容器不以任何方式跟踪会话:
ServletContextListener
答案 7 :(得分:1)
对于RESTful应用程序,我每次请求的生命周期结束时都会使其无效。可能有一些Web服务器总是在新客户端访问时创建新会话,无论您是否呼叫request.getSession()
。
答案 8 :(得分:0)
无法避免会话创建。但是,您可以在请求周期结束时检查是否违反了自己的要求。因此,创建一个简单的servlet过滤器,将其放在第一个和之后。如果创建了一个会话,则链接后会抛出异常:
chain.doFilter(request, response);
if(request.getSession(false) != null)
throw new RuntimeException("Somewhere request.getSession() was called");