Ok I got this working. What I needed to do was add my j2eePreAuthenticatedProcessingFilter with the custom-filter position set to PRE_AUTH_FILTER. Here is my new namespace based security configuration:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.2.xsd">
<http auto-config="false" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint" >
<intercept-url pattern="/secure/**" access="ROLE_ADMIN" />
<intercept-url pattern="/insecure/**" access="IS_AUTHENTICATED_FULLY" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<anonymous />
<logout />
<concurrent-session-control max-sessions="1"
exception-if-maximum-exceeded="true" />
</http>
<b:bean id="myPreAuthFilter"
class="org.springframework.security.ui.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
<custom-filter position="PRE_AUTH_FILTER"/>
<b:property name="authenticationManager" ref="authenticationManager" />
</b:bean>
<b:bean id="preAuthenticatedProcessingFilterEntryPoint"
class="org.springframework.security.ui.preauth.PreAuthenticatedProcessingFilterEntryPoint" />
<b:bean id="preAuthenticatedAuthenticationProvider"
class="org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider">
<custom-authentication-provider />
<b:property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</b:bean>
<b:bean id="preAuthenticatedUserDetailsService" class="com.XXX.security.userdetails.MyUserDetails" />
<authentication-manager alias="authenticationManager"/>
</b:beans>
I've attached my web.xml as well:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd"
version="2.4">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext-*.xml
</param-value>
<!--
<param-value>/WEB-INF/classes/applicationContext*.xml</param-value>
-->
</context-param>
<mime-mapping>
<extension>htc</extension>
<mime-type>text/x-component</mime-type>
</mime-mapping>
<listener>
<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>
<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>MyRealm</realm-name>
<form-login-config>
<form-login-page>/login.htm</form-login-page>
<form-error-page>/login.htm?retry=true</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>ROLE_CONTAINER_AUTH</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>All areas</web-resource-name>
<url-pattern>*.htm</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>ROLE_CONTAINER_AUTH</role-name>
</auth-constraint>
</security-constraint>
<servlet>
<servlet-name>realm</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>realm</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain
</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain
</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Here is the code for MyUserDetails.java if anyone is interested. I didn't want any container roles coming into the ACEGI security. That's just to get past the container to ACEGI can do its thing.
Code:
package com.cme.security.userdetails;
import java.util.ArrayList;
import java.util.List;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.userdetails.User;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.util.Assert;
public class MyUserDetails implements AuthenticationUserDetailsService {
public final UserDetails loadUserDetails(Authentication token) throws AuthenticationException {
Assert.notNull(token.getDetails());
UserDetails ud = createuserDetails(token);
return ud;
}
/**
* Creates the final <tt>UserDetails</tt> object. Can be overridden to customize the contents.
*
* @param token the authentication request token
* @param authorities the pre-authenticated authorities.
*/
protected UserDetails createuserDetails(Authentication token) {
List<GrantedAuthority> gaList = new ArrayList<GrantedAuthority>();
gaList.add(new GrantedAuthorityImpl("ROLE_USER"));
gaList.add(new GrantedAuthorityImpl("ROLE_CONTAINER_AUTH"));
if (token.getName().toUpperCase().contains("ADMIN")){
gaList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
}
return new User(token.getName(), "N/A", true, true, true, true, gaList.toArray(new GrantedAuthority[0]));
}
}
If anyone sees a way to improve on this approach I'd be glad to hear it. I'd still like to avoid any security-role or auth-constraints in the web.xml, but ACEGI doesn't redirect to the container login page (at least I don't know how configure it to do so). I hate having to add the ROLE_CONTAINER_AUTH to the realm authenticator (in this case the jetty hash realm) just to get past the container. It's a silly requirement because my enterprise wants us to use the container's security realm for authorization.
Thanks!