我想完全消除 HttpSession - 我可以在 web.xml 中执行此操作吗?我确信有特定于容器的方法可以做到这一点(当我进行谷歌搜索时,这就是拥挤的搜索结果)。
PS这是一个坏主意吗?在我真正需要它们之前,我更喜欢完全禁用它们。
我想完全消除 HttpSession - 我可以在 web.xml 中执行此操作吗?我确信有特定于容器的方法可以做到这一点(当我进行谷歌搜索时,这就是拥挤的搜索结果)。
PS这是一个坏主意吗?在我真正需要它们之前,我更喜欢完全禁用它们。
我想完全消除 HttpSession
你不能完全禁用它。您需要做的就是不要request.getSession()
通过 Web 应用程序代码中的任何一个或任何地方来处理它,request.getSession(true)
并确保您的 JSP 不会通过设置<%@page session="false"%>
.
如果您的主要关注点实际上是禁用在幕后使用的 cookie HttpSession
,那么您可以在 Java EE 5 / Servlet 2.5 中仅在特定于服务器的 webapp 配置中这样做。例如,在 Tomcat 中,您可以将cookies
属性设置为false
in<Context>
元素。
<Context cookies="false">
另请参阅此Tomcat 特定文档。这样,会话将不会保留在未重写 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>
如果您想在您的 web 应用程序中进行硬编码,以便getSession()
永远不会返回 a HttpSession
(或“空” HttpSession
),那么您需要创建一个过滤器,监听其中的一个,用返回所有方法url-pattern
的实现/*
替换,或者一个虚拟自定义什么都不做,甚至抛出.HttpServletRequest
HttpServletRequestWrapper
getSession()
null
HttpSession
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);
}
PS这是一个坏主意吗?在我真正需要它们之前,我更喜欢完全禁用它们。
如果您不需要它们,请不要使用它们。就这样。真的 :)
如果您正在构建一个无状态的高负载应用程序,您可以像这样禁用使用 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>
在带有 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 的区别
NEVER:Spring Security 永远不会创建 HttpSession,但如果 HttpSession 已经存在,则会使用它
STATELESS:Spring Security 永远不会创建 HttpSession 并且永远不会使用它来获取 SecurityContext
我对我的 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
将在创建或销毁会话时记录的日志,以便您可以跟踪它何时发生。
我想完全消除 HttpSession - 我可以在 web.xml 中执行此操作吗?我确定有容器特定的方法可以做到这一点
我不这么认为。禁用HttpSession
将违反 Servlet 规范,该规范规定HttpServletRequest#getSession
应返回会话或创建会话。所以我不希望 Java EE 容器提供这样的配置选项(这会使其不兼容)。
这是一个坏主意吗?在我真正需要它们之前,我更喜欢完全禁用它们。
好吧,我真的不明白这一点,如果你不想使用它,就不要在会话中放任何东西。现在,如果您真的想阻止会话的使用,您可以使用 aFilter
将请求替换为HttpServletRequestWrapper
覆盖的实现getSession()
。但我不会浪费时间来实现这个:)
更新:我最初的建议不是最佳的,“正确”(咳嗽)的方式是替换请求。
您可以使用 URL 重写过滤器(例如tukey rewrite filter )重写 URL,而不是禁用。这将为 Google 提供友好的结果,但仍允许基于 cookie 的会话处理。
但是,您可能应该为所有响应禁用它,因为它比搜索引擎不友好更糟糕。它公开了可用于某些安全漏洞的会话 ID 。
Tuckey 过滤器的示例配置:
<outbound-rule encodefirst="true">
<name>Strip URL Session ID's</name>
<from>^(.*?)(?:\;jsessionid=[^\?#]*)?(\?[^#]*)?(#.*)?$</from>
<to>$1$2$3</to>
</outbound-rule>
contextInitialized
从 Servlet 3.0 开始,您可以通过将这样的代码添加到a 的方法中,使 servlet 容器不以任何方式跟踪会话ServletContextListener
:
servletContext.setSessionTrackingModes(Collections.emptySet());
对于 RESTful 应用程序,我只是在每次请求的生命周期结束时使其无效。无论您是否调用,当新客户端访问时,可能有一些 Web 服务器总是创建新会话request.getSession()
。
无法避免会话创建。但是您可以在请求周期结束时检查您是否违反了自己的要求。因此,创建一个简单的 servlet 过滤器,如果创建了会话,则将其放置在 chain.doFilter 的第一个和之后:
chain.doFilter(request, response);
if(request.getSession(false) != null)
throw new RuntimeException("Somewhere request.getSession() was called");