Customizing HTTP Headers

We are trying to customize the HTTP response headers due to security requirements. How to do this in Vaadin?
Here is what we have tried but it does not work when WebSockets/Push is enabled. How would we do it for WebSockets?

@WebServlet
(
asyncSupported = Constants.USE_ASYNC,
initParams =
{
//@WebInitParam( name = Constants.InitParams.PUSH_MODE, value = Constants.InitParamValues.PUSH_MODE ),
//@WebInitParam( name = Constants.InitParams.WEBSOCKETS_SERVLET3, value = “true” ),
}
)
@WebListener
public class UIServlet
extends VaadinServlet
implements ServletContextListener, SessionInitListener, SessionDestroyListener, Serializable
{
protected void service( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException
{
getService().addSessionInitListener( new SessionInitListener()
{
public void sessionInit( SessionInitEvent event )
throws ServiceException
{
event.getSession().addRequestHandler( new CustomHeaderRequesthandler() );
}
} );
}

private class CustomHeaderRequesthandler
    implements RequestHandler
{
    public boolean handleRequest( VaadinSession session, VaadinRequest request, VaadinResponse response )    throws IOException
    {
        response.setHeader( "Cache-Control", "private, no-cache, must-revalidate, max-age=0, no-transform" );
        //response.setHeader( "Content-Security-Policy", "script-src 'self'; image-src 'self';" );
        response.setHeader( "Expires", "0" );
        response.setHeader( "Pragma", "no-cache" );
        response.setHeader( "Strict-Transport-Security", "max-age=31622400; includeSubDomains" );
        response.setHeader( "X-Content-Type-Options", "DENY" );
        response.setHeader( "X-XSS-Protection", "mode=block" );
        return false;
    }
}

}

Sorry, forgot to mention that this is for Vaadin 7.

Ok, so this means that Vaadin has a serious security hole. If you can’t set the HTTP headers then you cannot disable certain types of attacks. Not good.

Hi, for what I know about websockets, after the handshake over http protocol,
there are only text or binary messages exchanged by client an server, so there are no http headers.
But maybe I’m wrong

With Tomcat, you can set many of those in your web.xml (or Tomcat’s common web.xml) via the httpHeaderSecurity filter.

But I don’t know if that translates to websockets either, and of course wouldn’t if it’s not HTTP. I’d guess that websockets tunnels through the HTTP(S) port though for reasons of firewall access.

We seem to note that requests over websockets are perhaps not used by Tomcat to update the Http Session last accessed time, so it’s possible that Vaadin/atmosphere/websockets have issues at least with Tomcat 8.5, or we’re not configuring it just right yet.

I think we need to test it more thoroughly ourselves. We have set the Tomcat security filters and we can get most of what we need but not all. And if WebSockets not being HTTP means that it is not susceptible to identified attacks we may be ok.

The way that it is supposed to work is that if your application sets HTTP headers, the servlet container is not supposed to set those headers because setting them in the serlvet container (Connector) effects all applications using that Connector. If the Connector is used to access only one application then that might be ok. But different applications may have different requirements for HTTP headers. That’s the nature of Servlets.

The problem is that Vaadin redirects away from any registered request handlers on the service when WebSockets is enabled, so there is no way for your application to apply its own HTTP headers. The issue is that most companies now are using automated security scanners that run against all HTTP services and if they don’t see the right headers you get dinged and you have to explain why your application is not setting these headers.

Hopefully, we can get away with explaining that the HTTP part of the application is just a shell. All data communication happens via WebSockets, which is, hopefully, not susceptible to the same HTTP-based attacks.

Quoting the WebSocket Wikipedia article: “Its only relationship to HTTP is that its handshake is interpreted by HTTP servers as an Upgrade request.” Thus, the websocket connection only looks like HTTP(S) until the upgrade command, and is not really behaving like HTTP otherwise but uses a completely different protocol over the same port. For this reason, most HTTP headers should be irrelevant.

This said, I’d strongly recommend using HTTPS for all applications in production to encrypt all communication and provide an additional layer of security.