I have been working with Flex for a project at work the last 3 months, and am very, very thrilled by the possibilites it offers. While evaluating, i also looked at Flex Data Services, a J2EE web application that enables a tight interaction between flex and java on the server, much thighter even than with the webservice method that doesn't need the FDS. Especially the Message Queue Support for pushing Information to the browser catched my eye, so i started re-working a private project i had lying around for long where i kept a socket open and constantly loading, parsing the incoming data with javascript the moment it arrives, thus giving the illusion of browser push. This sucked badly, and the much cleaner FDS / Flex solution is working like a charm - but one thing was bugging me. The whole security system provided by flex is based on Container-Based-Security; This renders the wonderful Acegi Security annotations useless; So i needed integration.

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.