I looked far and wide for a nice solution, and finally came up with one of my own. flex.messaging.security.LoginCommand Interface implementations are shipped for different containers like cataline/tomcat, jboss, webspehere etc, but can also be replaced by custom implementations in WEB-INF/flex/services-config.xml in the <security> section.
Having used a dao authentication provider with acegi security and spring, i wrote the following class:
package my.own.security;
import java.security.Principal;
import java.util.List;
import javax.servlet.ServletConfig;
import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.AuthenticationProvider;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import flex.messaging.security.LoginCommand;
public class AcegiLoginCommand implements LoginCommand {
private static final Log log = LogFactory.getLog( AcegiLoginCommand.class );
protected static ApplicationContext applicationContext;
private static String[] CONFIG_LOCATIONS = {
"classpath:applicationContext.xml"
};
private static AuthenticationProvider authenticationProvider;
public AcegiLoginCommand() {
super();
if ( applicationContext == null ) {
log.debug( "Initializing Spring context");
try {
applicationContext = new ClassPathXmlApplicationContext(
getConfigLocations() );
} catch (Exception ex) {
log.error("exception loading spring context",ex);
}
log.debug( "... done !" );
}
if(authenticationProvider == null) {
authenticationProvider =
(AuthenticationProvider)applicationContext.getBean(
"myAuthenticationProviderSpringBean");
}
}
public Principal doAuthentication(String username, Object credentials) {
Authentication auth = authenticationProvider.authenticate(
new UsernamePasswordAuthenticationToken(username, credentials));
SecurityContextHolder.getContext().setAuthentication(auth);
return (Principal)auth;
}
public boolean doAuthorization(Principal arg0, List arg1) {
GrantedAuthority[] roles = ((UsernamePasswordAuthenticationToken)arg0).getAuthorities();
for(int n =0; n < roles.length; n++) {
for(int m = 0; m < arg1.size(); m++ ) {
if(roles[n].getAuthority().equals(arg1.get(m))) return true;
}
}
return false;
}
public boolean logout(Principal arg0) {
log.debug("logout called with arg: " + arg0);
// TODO
return false;
}
public void start(ServletConfig arg0) {
log.debug("start called with arg: " + arg0);
// TODO
}
public void stop() {
log.debug("stop called");
// TODO
}
private static String[] getConfigLocations() {
return CONFIG_LOCATIONS;
}
}
i never saw the items marked with TODO called up to now.
i then replaced the default LoginCommand in services-config.xml with the following:
<login-command class="my.own.security.AcegiLoginCommand" server="Tomcat"/>
The latter part (server=) i'm not sure about, i'm using tomcat, so it will be used, but maybe "*" would be better. It needs to be noted, that i deploy my web application inside the flex webapp, or to put it in correct terms, i added the contents of the flex web application to my webapp, so cross-webapp-security is out of the question in this specific case.
maybe it's of use to someone else, it cost me a few days to figure this out. remember, this is only important if using non-http(s)-transports like rtmp, because there is no acegi session filter for it.