Spring Security, trailing slashes, and dots in URLs

Viewed 9640

I use Spring Security 3.1.4 to secure a Spring MVC 3.2.4 application deployed to Tomcat. I have the following Spring Security configuration:

<http auto-config="true" use-expressions="true">
   <http-basic />
   <logout ... />
   <form-login ... />

   <intercept-url pattern="/" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/about" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/login" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/under-construction" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/admin-task*" access="hasRole('ROLE_USER') and hasRole('ROLE_ADMINISTRATOR')" />
   <intercept-url pattern="/resources/**" access="isAnonymous() or hasRole('ROLE_USER')" />
   <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</http>

I noticed that URL patterns without a trailing slash (e.g., /about) do not match URLs with a trailing slash (e.g., /about/) and vice-versa. In other words, a URL with a slash and an identical URL without a slash are treated as two different URLs by Spring Security. The problem could be fixed by using two security rules:

<intercept-url pattern="/about" access="isAnonymous() or hasRole('ROLE_USER')" />
<intercept-url pattern="/about/" access="isAnonymous() or hasRole('ROLE_USER')" />

Is there a better solution?

I know that path-type="regex" allows to define URL patterns with regular expressions, but I would like to avoid any unnecessary complexity if it's possible.

Update

As Adam Gent noted, there is an additional problem that involves URLs with a dot: /about.foo and /about are treated as the same URL by Spring MVC. However, Spring Security treats them as two different URLs. So, one more security rule may be necessary:

<intercept-url pattern="/about.*" .../>
3 Answers

I have used separate patterns for the same url. It is working for Spring security 3.1.7.RELEASE

<security:intercept-url pattern="/mypage./**" access="hasAnyRole('admin','reportviewer')"/>
<security:intercept-url pattern="/mypage" access="hasAnyRole('admin','reportviewer')"/>
<security:intercept-url pattern="/mypage/**" access="hasAnyRole('admin','reportviewer')"/>
Related