Tomcat 5.5, Struts 2, Spring, and SpringSecurity with Tomcat's security manager on

I have a Tomcat 5.5 server, running an app using:

Struts 2
Spring
Spring Security

I highly recommend Spring Security. Now, I need to have a couple of files that are accessed that are outside of the webapp/myapp directory. The way to do this is with the Tomcat security policy file. According to the documentation, you enable it with:

$TOMCAT_HOME/bin/startup.sh -security

This should read the $TOMCAT_HOME/conf/catalina.policy file to allow such access. Now, the default policy does not allow Struts 2 and Spring to work, so it needs some tweaking just to allow the application to start. Read on for my struggles with this.

First, just trying to start the app with the default policy file, I got errors:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.AuthenticationProviderBeanDefinitionParser$AuthenticationProviderCacheResolver#0': Instantiation of bean failed; nested exception is java.security.AccessControlException: access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)

Now, I'm not going to post the whole stack trace, but what I need to know is: java.security.AccessControlException: access denied (java.lang.reflect.ReflectPermission suppressAccessChecks)

This tells me that I need to modify the catalina.policy file to allow my webapp the permission java.lang.reflect.ReflectPermission with the argument suppressAccessChecks. This tells Tomcat to allow reflection (Which both Spring and Struts need).

So, I added the following to the Tomcat policy file, and got rid of this error:

grant codeBase "file:${catalina.home}/webapps/myapp/-" {
  permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};

This tells Tomcat to allow anything in the ./webapps/myapp directory (via the -) to have this permission.

I restarted, and got another permission error. I fixed that, too, and got another. Here's what I wound up with in the policy file:

grant codeBase "file:${catalina.home}/webapps/myapp/-" {
  permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
  permission java.io.FilePermission "${catalina.home}${file.separator}myapp${file.separator}*", "read";
  permission java.lang.RuntimePermission "accessDeclaredMembers";
  permission java.util.PropertyPermission "xwork.*", "read";
 };

If you look at the exceptions and figure out which permission you need to add by the exception, you can tailor yours, as well.

Then, I got this exception, which does not really make sense as to why.

exception
 
javax.servlet.ServletException: Could not initialize class org.springframework.security.context.SecurityContextHolder
	org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:294)
	org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:218)
 
root cause
 
java.lang.NoClassDefFoundError: Could not initialize class org.springframework.security.context.SecurityContextHolder
	org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:239)
	org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
	org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
	org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
	org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
	org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	java.lang.reflect.Method.invoke(Method.java:597)
	org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:244)
	java.security.AccessController.doPrivileged(Native Method)
	javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
	org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:276)
	org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:218)

If I change my policy file to this, the app works, so it is a security setting:

grant codeBase "file:${catalina.home}/webapps/myapp/-" {
  permission java.security.AllPermission;
};

Currently, that's where I am.