I've recently added Java Melody to a grails application. So I wanted to restrict the IP addresses that can access the monitoring endpoint, and also add basic auth for it so that not anyone can access the monitoring endpoint once the application is released for public use.
I've added filters to my web.xml, according to their documentation (https://github.com/javamelody/javamelody/wiki/UserGuide#16-security).
They look like this:
<filter>
<filter-name>javamelody</filter-name>
<filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
<init-param>
<param-name>authorized-users</param-name>
<param-value>user1:pwd1</param-value>
</init-param>
<init-param>
<param-name>allowed-addr-pattern</param-name>
<param-value>192\.168\.1\.*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>javamelody</filter-name>
<url-pattern>/monitoring</url-pattern>
</filter-mapping>
I've verified that it works when I run the application using grails run-app. If i try to access the monitoring endpoint, I am prompted for a username and password.
However, when I create a war file and deploy it to run on a jetty instance, the security filters don't work anymore. I can access the monitoring endpoint without providing a username and password.
Can anyone help me? I'm new to this and I really don't know how to proceed with this problem. I searched around for answers but nothing really fits the bill. I'm not sure if the issue is with Java Melody or with Jetty.
Appreciate all the help I can get. Thanks!
EDIT:
My whole web.xml used in grails prod run-app
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
metadata-complete="true"
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>/@grails.project.key@</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>@grails.project.key@</param-value>
</context-param>
<filter>
<filter-name>charEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>characterEncodingFilter</param-value>
</init-param>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter>
<filter-name>javamelody</filter-name>
<filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
<init-param>
<param-name>authorized-users</param-name>
<param-value>user1:pwd1</param-value>
</init-param>
<init-param>
<param-name>allowed-addr-pattern</param-name>
<param-value>192\.168\.1\.*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>charEncodingFilter</filter-name>
<url-pattern>/ *</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>javamelody</filter-name>
<url-pattern>/monitoring</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener</listener-class>
</listener>
<!-- Grails dispatcher servlet -->
<servlet>
<servlet-name>grails</servlet-name>
<servlet-class>org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet</servlet-class>
<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<!-- The Groovy Server Pages servlet -->
<servlet>
<servlet-name>gsp</servlet-name>
<servlet-class>org.codehaus.groovy.grails.web.pages.GroovyPagesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gsp</servlet-name>
<url-pattern>*.gsp</url-pattern>
</servlet-mapping>
<session-config>
<!-- 30 minutes -->
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<!--
The order of the welcome pages is important. JBoss deployment will
break if index.gsp is first in the list.
-->
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.gsp</welcome-file>
</welcome-file-list>
Web.xml of my WAR file:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" metadata-complete="true" version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<display-name>/radius-api-production-0.1</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>radius-api-production-0.1</param-value>
</context-param>
<context-param>
<param-name>sample</param-name>
<param-value>Sample Value</param-value>
</context-param>
<context-param>
<param-name>javamelody.displayed-counters</param-name>
<param-value>http,sql,error,log,spring,jsp</param-value>
</context-param>
<filter>
<filter-name>monitoring</filter-name>
<filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>charEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>characterEncodingFilter</param-value>
</init-param>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter>
<filter-name>AssetPipelineFilter</filter-name>
<filter-class>asset.pipeline.AssetPipelineFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>javamelody</filter-name>
<filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>authorized-users</param-name>
<param-value>user1:pwd1</param-value>
</init-param>
</filter>
<filter>
<filter-name>urlMapping</filter-name>
<filter-class>org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>hiddenHttpMethod</filter-name>
<filter-class>org.codehaus.groovy.grails.web.filters.HiddenHttpMethodFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>grailsWebRequest</filter-name>
<filter-class>org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>grailsCacheFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>charEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>hiddenHttpMethod</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>javamelody</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AssetPipelineFilter</filter-name>
<url-pattern>/assets/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>grailsWebRequest</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>monitoring</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>urlMapping</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>grailsCacheFilter</filter-name>
<url-pattern>*.dispatch</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<listener>
<listener-class>net.bull.javamelody.SessionListener</listener-class>
</listener>
<listener>
<listener-class>org.codehaus.groovy.grails.plugins.log4j.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>grails</servlet-name>
<servlet-class>org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet</servlet-class>
<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet>
<servlet-name>gsp</servlet-name>
<servlet-class>org.codehaus.groovy.grails.web.pages.GroovyPagesServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>grails-errorhandler</servlet-name>
<servlet-class>org.codehaus.groovy.grails.web.servlet.ErrorHandlingServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gsp</servlet-name>
<url-pattern>*.gsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>grails-errorhandler</servlet-name>
<url-pattern>/grails-errorhandler</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>grails</servlet-name>
<url-pattern>*.dispatch</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.gsp</welcome-file>
</welcome-file-list>
<error-page>
<error-code>500</error-code>
<location>/grails-errorhandler</location>
</error-page>