我可以关闭web.xml中的HttpSession吗?

时间:2010-02-12 23:37:11

标签: java session web-applications web.xml

我想完全消除HttpSession - 我可以在web.xml中这样做吗?我确信有容器特定的方法可以做到这一点(当我进行谷歌搜索时,这是搜索结果的主要内容)。

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

9 个答案:

答案 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 /* HttpServletRequestgetSession()替换为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过滤器

Example config

<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

Javadoc.

答案 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");