Wow, I got it to work
Thanks so much. This really is an amazing package!
Here is my subclass of SecurityEnforcementFilter
Code:
/**
* Overrides SecurityEnforcementFilter.sendAccessDeniedError. If a LoginAuthentication
* was found, it is removed and the integration entry point is used to handle normal login.
* Otherwise the accessDenied is a real error and control is returned to the superclass
* @author rcarver
*/
public class LoginAllowedSecurityEnforcementFilter extends SecurityEnforcementFilter {
protected static final Log log = LogFactory.getLog(LoginAllowedSecurityEnforcementFilter.class);
private AbstractIntegrationFilter integrationFilter;
/**
* @param integrationFilter The integrationFilter to set.
*/
public void setIntegrationFilter(AbstractIntegrationFilter integrationFilter) {
this.integrationFilter = integrationFilter;
}
public void afterPropertiesSet() throws Exception {
if (this.integrationFilter == null) {
throw new IllegalArgumentException("integrationFilter must be defined");
}
super.afterPropertiesSet();
}
/**
* @see net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter#sendAccessDeniedError(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
protected void sendAccessDeniedError(ServletRequest request, ServletResponse response) throws IOException {
Authentication authentication = (Authentication) integrationFilter.extractFromContainer(request);
log.debug("Handling access denied error");
if (authentication instanceof LoginAuthentication) {
log.debug("Found a LoginAuthentication, removing it from container");
integrationFilter.commitToContainer(request, null);
log.debug("Redirecting to login entryPoint");
try {
getAuthenticationEntryPoint().commence(request, response);
} catch (IOException e) {
throw e;
} catch (ServletException e) {
log.debug("Problem using authenticationEntryPoint", e);
}
return;
}
super.sendAccessDeniedError(request, response);
}
}
New ServletFilter to ensure a LoginAuthentication is available. This filter runs before other Acegi Security filters.
Code:
/**
* ServletFilter to provides a LoginAuthentication if no authentication was found. This should run
* before other Acegi Security filters.
* @author rcarver
*/
public class LoginAuthenticationPopulatingFilter implements Filter {
protected static final Log log = LogFactory.getLog(LoginAllowedSecurityEnforcementFilter.class);
private AbstractIntegrationFilter integrationFilter;
/**
* @param integrationFilter The integrationFilter to set.
*/
public void setIntegrationFilter(AbstractIntegrationFilter integrationFilter) {
this.integrationFilter = integrationFilter;
}
/**
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
Object auth = integrationFilter.extractFromContainer(request);
if (auth == null) {
log.debug("No Authentication was found, providing a LoginAuthentication");
integrationFilter.commitToContainer(request, new LoginAuthentication());
}
filterChain.doFilter(request, response);
}
/**
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig arg0) throws ServletException { }
/**
* @see javax.servlet.Filter#destroy()
*/
public void destroy() { }
}
LoginAuthentication is an extremely simple implementation of Authentication that is hardcoded with a single GrantedAuthority "ANONYMOUS_LOGIN"
Then, I just added a LoginAuthenticationProvider (which always authenticates), and a new role voter to allow ANONYMOUS_*
I think that's about it. Thanks again.