jpganz18
jpganz18

Reputation: 5858

Cookie http only with spring security and servlet 2.5?

I want to make my cookie secure and http request only.

Ive seen many post like this and seem to work fine, but using configuration files and servlet +3.

What I basically want to do is to set my cookie http only and (if possible) ssl only as well.

So far I added this to my web.xml

    <session-config>
        <session-timeout>60</session-timeout>
        <cookie-config>
            <http-only>true</http-only>
        </cookie-config>
        <tracking-mode>COOKIE</tracking-mode>
    </session-config>

doesnt do anything, as far as I was reading, I also have to configure my servlet.xml to enable this feature, but I dont know how...

Any idea how to do this?

EDIT:

Since I am using servlets 2.5 the xml configuration is not an option, maybe a filter?

Upvotes: 10

Views: 22413

Answers (5)

Dipak Prajapati
Dipak Prajapati

Reputation: 528

With the help of ServletContextListener we have control at servlet at tomcat startup and shutdown. So here on tomcat startup we are setting the configuration of httponly.

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public final class ContextListener implements ServletContextListener {

    private ServletContext context = null;
    @Override
    public void contextDestroyed(ServletContextEvent event) {
        this.context = null;
    }
    @Override
    public void contextInitialized(ServletContextEvent event) {
        this.context = event.getServletContext();
        this.context.getSessionCookieConfig().setHttpOnly(true);

    }
}

Abb beloww entry in web.xml

<listener>
<description>contextListener</description>
<listener-class>
        main.ContextListener 
    </listener-class>
 </listener>

Upvotes: 0

Rick Pearce
Rick Pearce

Reputation: 63

We ran across this issue recently. I tried the property settings for http-only, which worked locally, but not when we deployed to our test env. It's possible there were some default settings in the env overriding those local settings. What worked was to set the properties in a Spring config file:

@Bean
public ServletContextInitializer servletContextInitializer() {
    return new ServletContextInitializer() {
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
            SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
            sessionCookieConfig.setHttpOnly(true);
            sessionCookieConfig.setSecure(true);
        }
    };
}

Upvotes: 3

jakub.josef
jakub.josef

Reputation: 530

I hate XML configuration, so i spend some time for find non-XML solution.

Since Spring Security 1.3 you can use

server.session.cookie.http-only=true
server.session.cookie.secure=true

in your application.properties file.

Maybe there is a way to set this using pure Java Configuration, but i can't find them.

Upvotes: 5

Barett
Barett

Reputation: 5948

The context.xml changes mentioned by javagc will only reconfigure your session cookie.

To change all of your cookies, you have 2 options:

Option 1) Update your application code to add cookies using a more secure method. Example: https://stackoverflow.com/a/30488471/95674

Option 2) You can configure a servlet filter to change ALL (other) cookies coming through the system. Add these 2 classes into the appropriate package in your WAR. Then update your web.xml as detailed below.

There is a simpler example of Option 2 listed on the OWASP site, if you are willing to add a dependency on the OWASP libraries. That is located here: https://www.owasp.org/index.php/HttpOnly#Using_Java_to_Set_HttpOnly

Response Wrapper

This adds the http only flag to all cookies on the wrapped response.

public class HttpOnlyResponseWrapper extends HttpServletResponseWrapper {

 public HttpOnlyResponseWrapper(HttpServletResponse res) {
   super(res);
 }

 public void addCookie(Cookie cookie) {
   StringBuilder header = new StringBuilder();
   if ((cookie.getName() != null) && (!cookie.getName().equals(""))) {
     header.append(cookie.getName());
   }
   if (cookie.getValue() != null) {
     // Empty values allowed for deleting cookie
     header.append("=" + cookie.getValue());
   }

   if (cookie.getVersion() == 1) {
     header.append(";Version=1");
     if (cookie.getComment() != null) {
       header.append(";Comment=\"" + cookie.getComment() + "\"");
     }
     if (cookie.getMaxAge() > -1) {
       header.append(";Max-Age=" + cookie.getMaxAge());
     }
   } else {
     if (cookie.getMaxAge() > -1) {
       Date now = new Date();
       now.setTime(now.getTime() + (1000L * cookie.getMaxAge()));
       SimpleDateFormat cookieFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz");
       header.append(";Expires=" + cookieFormat.format(now));
     }
   }

   if (cookie.getDomain() != null) {
     header.append(";Domain=" + cookie.getDomain());
   }
   if (cookie.getPath() != null) {
     header.append(";Path=" + cookie.getPath());
   }
   if (cookie.getSecure()) {
     header.append(";Secure");
   }
   header.append(";httpOnly");
   addHeader("Set-Cookie", header.toString());
 }
}

Filter

This Filter wraps configured responses in the above wrapper.

package yourpackage;

@WebFilter(filterName = "HttpOnlyFilter", urlPatterns = {"/*"})
public class HttpOnlyFilter implements Filter {
 private FilterConfig config;

 @Override
 public void destroy() {
   this.config = null;
 }

 @Override
 public void doFilter(ServletRequest req, ServletResponse res,
     FilterChain chain) throws IOException, ServletException {

   HttpOnlyResponseWrapper hres = new HttpOnlyResponseWrapper((HttpServletResponse)res);
   chain.doFilter(req, hres);
 }

 public FilterConfig getFilterConfig() {
   return this.config;
 }

 @Override
 public void init(FilterConfig config) throws ServletException {
   this.config = config;
 }
}

Adapted (WARNING: NOT an exact copy!) from source: http://sylvanvonstuppe.blogspot.com/2007/07/servlet-filter-for-httponly.html

web.xml

One last detail: ONLY IF you have annotation scanning turned OFF in your system like this:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         version="2.5" ***metadata-complete="true"***>
</web-app> 

Then you will need to manually configure the above Filter in your web.xml file, like this:

<filter>
    <filter-name>HttpOnlyFilter
    <filter-class>yourpackage.HttpOnlyFilter
</filter>
<filter-mapping>
    <filter-name>HttpOnlyFilter
    <url-pattern>/*
</filter-mapping>

If your app scans annotations (which is the default), the web.xml part is not necessary.

Upvotes: 1

Danny Varela
Danny Varela

Reputation: 74

I believe you are missing the security tag. Try adding:

<secure>false</secure>

Upvotes: -1

Related Questions