60

我想完全消除 HttpSession - 我可以在 web.xml 中执行此操作吗?我确信有特定于容器的方法可以做到这一点(当我进行谷歌搜索时,这就是拥挤的搜索结果)。

PS这是一个坏主意吗?在我真正需要它们之前,我更喜欢完全禁用它们。

4

9 回答 9

79

我想完全消除 HttpSession

你不能完全禁用它。您需要做的就是不要request.getSession()通过 Web 应用程序代码中的任何一个或任何地方来处理它,request.getSession(true)并确保您的 JSP 不会通过设置<%@page session="false"%>.

如果您的主要关注点实际上是禁用在幕后使用的 cookie HttpSession,那么您可以在 Java EE 5 / Servlet 2.5 中仅在特定于服务器的 webapp 配置中这样做。例如,在 Tomcat 中,您可以将cookies属性设置为falsein<Context>元素。

<Context cookies="false">

另请参阅此Tomcat 特定文档。这样,会话将不会保留在未重写 URL 的后续请求中——仅当您出于某种原因从请求中获取它时。毕竟,如果您不需要它,不要抓住它,那么它根本不会被创建/保留。

或者,如果您已经在 J​​ava 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的实现/*替换,或者一个虚拟自定义什么都不做,甚至抛出.HttpServletRequestHttpServletRequestWrappergetSession()nullHttpSessionUnsupportedOperationException

@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这是一个坏主意吗?在我真正需要它们之前,我更喜欢完全禁用它们。

如果您不需要它们,请不要使用它们。就这样。真的 :)

于 2010-02-13T01:01:20.397 回答
10

如果您正在构建一个无状态的高负载应用程序,您可以像这样禁用使用 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>
于 2015-10-28T15:48:32.123 回答
6

在带有 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

于 2017-02-10T09:09:53.220 回答
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将在创建或销毁会话时记录的日志,以便您可以跟踪它何时发生。

于 2013-12-30T05:48:45.423 回答
2

我想完全消除 HttpSession - 我可以在 web.xml 中执行此操作吗?我确定有容器特定的方法可以做到这一点

我不这么认为。禁用HttpSession将违反 Servlet 规范,该规范规定HttpServletRequest#getSession应返回会话或创建会话。所以我不希望 Java EE 容器提供这样的配置选项(这会使其不兼容)。

这是一个坏主意吗?在我真正需要它们之前,我更喜欢完全禁用它们。

好吧,我真的不明白这一点,如果你不想使用它,就不要在会话中放任何东西。现在,如果您真的想阻止会话的使用,您可以使用 aFilter将请求替换为HttpServletRequestWrapper覆盖的实现getSession()。但我不会浪费时间来实现这个:)

更新:我最初的建议不是最佳的,“正确”(咳嗽)的方式是替换请求。

于 2010-02-13T00:56:16.570 回答
2

您可以使用 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>
于 2010-02-13T00:57:28.367 回答
2

contextInitialized从 Servlet 3.0 开始,您可以通过将这样的代码添加到a 的方法中,使 servlet 容器不以任何方式跟踪会话ServletContextListener

servletContext.setSessionTrackingModes(Collections.emptySet());

Java 文档。

于 2018-07-18T21:29:36.210 回答
1

对于 RESTful 应用程序,我只是在每次请求的生命周期结束时使其无效。无论您是否调用,当新客户端访问时,可能有一些 Web 服务器总是创建新会话request.getSession()

于 2012-09-26T12:33:15.637 回答
1

无法避免会话创建。但是您可以在请求周期结束时检查您是否违反了自己的要求。因此,创建一个简单的 servlet 过滤器,如果创建了会话,则将其放置在 chain.doFilter 的第一个和之后:

chain.doFilter(request, response);
if(request.getSession(false) != null)
    throw new RuntimeException("Somewhere request.getSession() was called");
于 2014-09-18T14:47:01.970 回答