Question

I am upgrading a web application (Servlet 3.0 / Tomcat 7) that requires basic authentication on most of its pages. This application has a small set of monitoring servlets, none of which should be protected. In my web.xml, I currently have the following security-constraint blocks (private info replaced by letters of the alphabet):

<security-constraint>
    <display-name>Security Constraint</display-name>
    <web-resource-collection>
        <web-resource-name>Protected Area</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>CN=A,OU=B,OU=C,OU=D,DC=E,DC=F</role-name>
    </auth-constraint>
</security-constraint>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Unprotected Pages</web-resource-name>
        <url-pattern>/health/*</url-pattern>
    </web-resource-collection>
</security-constraint>

Within the "health" path there are three endpoints:

  • /health/monitor/status
  • /health/monitor/version
  • /health/monitor/version/xml

When I visit either of the version endpoints, I am not prompted for credentials (as expected). However when I visit the status page, the browser presents me with a basic authentication box. When I hit "Cancel", I'm allowed to load the page normally. Likewise if I've already logged in, I will not be prompted again by the status screen until my login expires.

I realize that this could be solved by not having the secure content deployed to /*, but moving it would be a lot of work changing hard-coded paths and testing (it's a very old application)... and I have 5 or 6 more to do. I'm open to doing this if necessary, but I wanted to find out if this is possible without changing any secure content paths. I do have complete freedom over the paths of the monitoring servlets.

This seems related to Tomcat 7 - Multiple security-constraints not working but rather than total failure just one of my endpoints is failing, which I find very strange. I've spent some time searching and it looks like what I'm doing should work... but it doesn't.

I'm using web-app version 3.0, deploying to Tomcat 7 (have tried versions 7.0.42 and 7.0.47). I have already tried changing the order of the security-constraint blocks.

Thoughts?

Here is my full web.xml for reference (note the monitoring servlets are managed via Java annotations, so are not present):

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
     xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<display-name>TPS</display-name>

<servlet>
    <servlet-name>CFMLServlet</servlet-name>
    <servlet-class>railo.loader.servlet.CFMLServlet</servlet-class>
    <init-param>
      <param-name>configuration</param-name>
      <param-value>/WEB-INF/railo/</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
    <servlet-name>AMFServlet</servlet-name>
    <servlet-class>railo.loader.servlet.AMFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
    <servlet-name>AttachmentServlet</servlet-name>
    <servlet-class>com.package.toolshed.AttachmentServlet</servlet-class>
    <init-param>
        <param-name>configFilePath</param-name>
        <param-value>com/package/toolshed/configuration/tps-config.xml</param-value>
    </init-param>
    <init-param>
        <param-name>configPathParam</param-name>
        <param-value>attachment.servlet.pathPrefix</param-value>
    </init-param>
    <load-on-startup>6</load-on-startup>
</servlet>


<servlet-mapping>
    <servlet-name>CFMLServlet</servlet-name>
    <url-pattern>*.cfm</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>CFMLServlet</servlet-name>
    <url-pattern>*.cfml</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>CFMLServlet</servlet-name>
    <url-pattern>*.cfc</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>AMFServlet</servlet-name>
    <url-pattern>/flashservices/gateway/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>AttachmentServlet</servlet-name>
    <url-pattern>/attachments/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<welcome-file-list>
    <welcome-file>index.cfm</welcome-file>
    <welcome-file>index.cfml</welcome-file>
</welcome-file-list>

<security-constraint>
    <display-name>Security Constraint</display-name>
    <web-resource-collection>
        <web-resource-name>Protected Area</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>CN=A,OU=B,OU=C,OU=D,DC=E,DC=F</role-name>
    </auth-constraint>
</security-constraint>

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Unprotected Pages</web-resource-name>
        <url-pattern>/health/*</url-pattern>
    </web-resource-collection>
</security-constraint>

<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>TPS</realm-name>
</login-config>

<security-role>
    <role-name>CN=A,OU=B,OU=C,OU=D,DC=E,DC=F</role-name>
</security-role>
</web-app>
Was it helpful?

Solution

Figured this out.

It turns out that the status servlet was loading a CSS document, and that load was triggering the auth. What confuses me is that both status and version load JSPs, and these JSPs do not need to be considered in the security-constraint (one of the steps I took initially was to add *.jsp to my security constraint). The JSPs exist at the same path as the CSS.

New, working web.xml

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Unprotected Pages</web-resource-name>
        <url-pattern>/health/*</url-pattern>
        <url-pattern>/monitoringCommon.css</url-pattern>
    </web-resource-collection>
</security-constraint>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top