Can I turn off the HttpSession in web.xml?
Asked Answered
C

9

65

I would like to eliminate the HttpSession completely - can I do this in web.xml? I'm sure there are container specific ways to do it (which is what crowds the search results when I do a Google search).

P.S. Is this a bad idea? I prefer to completely disable things until I actually need them.

Cyndi answered 12/2, 2010 at 23:37 Comment(1)
What an interesting question. I have a situation where with Tomcat, no session is being created for me, so I was searching for whether there was a way to turn the session on in web.xml. :DLarondalarosa
S
82

I would like to eliminate the HttpSession completely

You can't entirely disable it. All you need to do is to just not to get a handle of it by either request.getSession() or request.getSession(true) anywhere in your webapplication's code and making sure that your JSPs don't implicitly do that by setting <%@page session="false"%>.

If your main concern is actually disabling the cookie which is been used behind the scenes of HttpSession, then you can in Java EE 5 / Servlet 2.5 only do so in the server-specific webapp configuration. In for example Tomcat you can set the cookies attribute to false in <Context> element.

<Context cookies="false">

Also see this Tomcat specific documentation. This way the session won't be retained in the subsequent requests which aren't URL-rewritten --only whenever you grab it from the request for some reason. After all, if you don't need it, just don't grab it, then it won't be created/retained at all.

Or, if you're already on Java EE 6 / Servlet 3.0 or newer, and really want to do it via web.xml, then you can use the new <cookie-config> element in web.xml as follows to zero-out the max age:

<session-config>
    <session-timeout>1</session-timeout>
    <cookie-config>
        <max-age>0</max-age>
    </cookie-config>
</session-config>

If you want to hardcode in your webapplication so that getSession() never returns a HttpSession (or an "empty" HttpSession), then you'll need to create a filter listening on an url-pattern of /* which replaces the HttpServletRequest with a HttpServletRequestWrapper implementation which returns on all getSession() methods null, or a dummy custom HttpSession implementation which does nothing, or even throws 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. Is this a bad idea? I prefer to completely disable things until I actually need them.

If you don't need them, just don't use them. That's all. Really :)

Schiedam answered 13/2, 2010 at 1:1 Comment(12)
The HttpServletRequestWrapper sounds good, I would go with that. In a large project with many developers you need some enforcement of architectural decisions (like statelessness). You can't rely on people "simply not using it".Fissure
"If you don't need them, just don't use them" It is not that simple. Some of the hundreds of libraries your project uses might create a session somewhere.Beacon
@David: then just question the library in question?Schiedam
@Balus so there is no application server that can handle requests without creating the HttpSession and storing the data for at least one minute? Right?Overmatch
It is so sad to see that Java EE was simply NOT designed for stateless, sessionless applications, which is one of the best modern technique to build scalable web applications. That is also the reason of emerging new technologies such as express.js and Play framework. They are stateless by default and they are indeed very scalable server side frameworks that can easily serve thousands concurrently on a single regular machine. I recommend using them for new projects.Hurricane
@bekce: Uh, whilst Java EE is indeed not stateless by default, you can make it (at least JSP, Servlets and JSF) stateless as answered above (simply don't touch HttpSession in first place). So I don't see why this would be a reason to migrate to an entirely different web framework. Moreover, scalability doesn't depend on statelessness at all. Look at Google as an example, it definitely isn't stateless :)Schiedam
@Schiedam Even if you don't touch that object, the server will definitely create one for you in the memory, which is terrible for GC and from security perspective if you have lots of them. The problem of Java EE is that it was designed to solve everything even load balancing, session replication, clustering, messaging all in suboptimal ways compared to current technology and it lost its competence along the way. Modern systems should use Redis or Hazelcast for session replication which scale well.Hurricane
@becke: "definitely"? Apparently you've only worked with buggy servers. This is namely nowhere defined in servlet spec. Even then, your GC and security concerns are ungrounded. Sorry, your subjective comments so far sound too much like fanboy speeches from a disgruntled user. Stack Overflow is not the right place for that. Try Reddit instead.Schiedam
@Schiedam Regarding JSP-s: in case we use the approach you suggested to override the getSession() methods, do we still need to explicitly add <%@page session="false"%> tags to JSP-s? Or do the automated session creation in the JSP lifecycle also fall back to the same getSession() methods?Robb
In my application, the jsp pages seem to implicitly create a session. I tried to use <%@page session="false"%> but then the page could not be loaded anymore. I also tried to disable cookies in the context.xml but it didn´t work either.Advice
@FranzDeschler: just put a breakpoint in session creation and inspect call stack to nail down who's doing that and why.Schiedam
@Schiedam thanks. It works now. I had to add it to all jsp files. Not only the root-jsp but all included ones too.Advice
B
10

If you are building a stateless high load application you can disable using cookies for session tracking like this (non-intrusive, probably container-agnostic):

<session-config>
    <tracking-mode>URL</tracking-mode>
</session-config>

To enforce this architectural decision write something like this:

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");
}
}

And add it to web.xml and fix places where it fails with that exception:

<listener>
    <listener-class>com.ideas.bucketlist.web.PreventSessionListener</listener-class>
</listener>
Barris answered 28/10, 2015 at 15:48 Comment(0)
G
7

In Spring Security 3 with Java Config, you can use HttpSecurity.sessionManagement():

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

Xml looks like this;

<http create-session="stateless">
  <!-- config -->
</http>

By the way, the difference between NEVER and STATELESS

NEVER:Spring Security will never create an HttpSession, but will use the HttpSession if it already exists

STATELESS:Spring Security will never create an HttpSession and it will never use it to obtain the SecurityContext

Greengrocery answered 10/2, 2017 at 9:9 Comment(2)
@ArtemNovikov What's your Spring Security version? This future is supported since 3.1Greengrocery
This means that Spring Security will never create an HttpSession but leaves open the door for other parts of code that can request the session creation by using getSession() as stated in BalusC answerFernandofernas
N
4

I use the following method for my RESTful app to remove any inadvertent session cookies from being created and used.

<session-config>
    <session-timeout>1</session-timeout>
    <cookie-config>
        <max-age>0</max-age>
    </cookie-config>
</session-config>

However, this does not turn off HttpSessions altogether. A session may still be created by the application inadvertently, even if it disappears in a minute and a rogue client may ignore the max-age request for the cookie as well.

The advantage of this approach is you don't need to change your application, just web.xml. I would recommend you create an HttpSessionListener that will log when a session is created or destroyed so you can track when it occurs.

Nocturn answered 30/12, 2013 at 5:48 Comment(0)
G
2

I would like to eliminate the HttpSession completely - can I do this in web.xml? I'm sure there are container specific ways to do it

I don't think so. Disabling the HttpSession would be a violation of the Servlet spec which states that HttpServletRequest#getSession should return a session or create one. So I wouldn't expect a Java EE container to provide such a configuration option (that would make it non compliant).

Is this a bad idea? I prefer to completely disable things until I actually need them.

Well, I don't really get the point, just don't put anything in the session if you don't want to use it. Now, if you really want to prevent the use of the session, you can use a Filter to replace the request with a implementation of HttpServletRequestWrapper overriding getSession(). But I wouldn't waste time implementing this :)

Update: My initial suggestion was not optimal, the "right" (cough) way would be to replace the request.

Giannagianni answered 13/2, 2010 at 0:56 Comment(0)
S
2

Rather than disabling you can rewrite the URL using a URL rewrite filter eg tuckey rewrite filter. This will give Google friendly results but still allow cookie based session handling.

However, you should probably disable it for all responses as it's worse than just search engine unfriendly. It exposes the session ID which can be used for certain security exploits.

Example config for Tuckey filter:

<outbound-rule encodefirst="true">
  <name>Strip URL Session ID's</name>
  <from>^(.*?)(?:\;jsessionid=[^\?#]*)?(\?[^#]*)?(#.*)?$</from>
  <to>$1$2$3</to>
</outbound-rule>
Smarten answered 13/2, 2010 at 0:57 Comment(0)
M
2

As of Servlet 3.0, you can make it so sessions are not tracked by the servlet container in any way, by adding code like this to the contextInitialized method of a ServletContextListener:

servletContext.setSessionTrackingModes(Collections.emptySet());

Javadoc.

Macmacabre answered 18/7, 2018 at 21:29 Comment(1)
Thank you. Worked fine with jetty. I needed a way to avoid session creation without having to ensure each .jsp had <%@ page session="false" %> configured and so far it is the best solution to meet my needs.Seymore
M
1

For RESTful application, I simply invalidate it every time the request's lifecycle ends. There may be some web server that always creates new session when new client access whether you call request.getSession() or not.

Misstep answered 26/9, 2012 at 12:33 Comment(0)
C
1

One cannot avoid the session creation. But you can check if you violate your own requirement at the end of a request cycle. So, create a simple servlet filter, which you place as first and after chain.doFilter throw an exception if a session was created:

chain.doFilter(request, response);
if(request.getSession(false) != null)
    throw new RuntimeException("Somewhere request.getSession() was called");
Calabash answered 18/9, 2014 at 14:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.