Editing my post:
After further evaluation, I am struggling with the same exact problem. If the first auth fails, the custom error page gets forwarded, Spring Sec intercepts and tries to reauth. And so on. It does not notice that auth has already failed. I cannot tell it's whether Tomcat or Spring Security. But since Spring Security performs auth, it must be the source of error.
I was able to reproduce this with the default basic filter with a LdapBindAuthenticator. I have found a resembling thread but with no real solution for that problem.
Here is my config:
I am on Tomcat 6.0.35, Spring Security 3.1.2, Spring 3.1.2
Code:
web.xml:
<servlet-mapping>
<servlet-name>dispatch</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher> <!-- This is necessary otherwise the security context won't be available on that pages -->
</filter-mapping>
<!-- error pages -->
<error-page>
<error-code>401</error-code>
<location>/errors/401</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/errors/403</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/errors/404</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/errors/500</location>
</error-page>
A controller handles all /errors/* requests.
Code:
spring-security.xml
<beans:bean id="securityContextPersistenceFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />
<security:http pattern="/ext-resources/**" security="none" />
<security:http pattern="/resources/**" security="none" />
<security:http use-expressions="true" realm="My Application">
<security:intercept-url
pattern="/app/**"
access="hasRole('User')" />
<security:intercept-url
pattern="/admin/**"
access="hasRole('Admin')" />
<security:logout invalidate-session="true" delete-cookies="JSESSIONID"
logout-url="/logout" logout-success-url="/logout-success" />
<security:http-basic />
</security:http>
<!-- followed by the LDAP configuration -->
If you remove the custom error pages, Tomcat's error report valve works as expected.
So, what can we do here? Is there an error in our logic?
Saying
Code:
<security:http pattern="/errors/401" security="none" />
may here for this page but what about 500? This page cannot be set to none. I'd like to retain the security there while displaying the occured error.