BlazeDS and Spring Security
I’ve been trying to figure out how to use Acegi security with BlazeDS, hopefully working it in with Spring MVC and this is what I ended up with. If anyone has other suggestions please let me know. This is a topic that really needs discussing.
The way you secure a destination in BlazeDS is you configure a <security-constraint> on the destination, and you specify the roles that are allowed to access the destination and, optionally, a list of methods on the destination that the authenticated user can invoke.
You then specify a LoginCommand which is specific to your servlet container. The job is this guy is to check the user’s credentials and log the user into the Servlet Container if the user is not logged in.
If you introduce Acegi into the mix, you suddenly have to deal with Spring specific authentication and authorization. At first I thought that I would have to write my own LoginCommand and maybe other stuff.
I decided to go with the lowest impact change possible.
First, I created a SpringFactory for my destinations, as described in Cristophe Coenraets blogs post Using Flex with Spring.
Next, instead of securing my destinations in the BlazeDS configuration files I created a BeanNameAutoProxyCreator and added my destinations, and passed it a securityInterceptor which lists the methods and roles that are allowed to access them. I also configured the web security interceptor filter chain and made sure that /messagebroker/** matched the chain. This should be the case if your filterInvocationDefinitionSource has /** as the path. What this means is that calls to /messagebroker/**, which is the url that a Flex app uses when talking to BlazeDS, pass through Spring’s security filter chain and have a chance to have the Authentication principal added to the context.
I setup simple Basic Authentication to avoid dealing with forms and login, for the moment.
I created a SampleService bean with two methods:
public class SampleService {
private String name; public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSecureName()
{
return "secure: " + name;
}
}
As I mentioned above, I added my destination bean to the autoProxyCreator:
<bean id="autoProxyCreator" ... >
<property name="interceptorNames">
...
<value>securityInterceptor</value>...
<property name="beanNames">
...
<value>sampleService</value>
...
</bean>
Configured the SecurityInterceptor to intercept calls to the getSecureName method.
<bean id="securityInterceptor">
...
<property name="objectDefinitionSource">
<value>com.machine501.bdss.SampleService.getSecureName=ROLE_ADMIN</value>
...
</bean>
Then, I created a Flex client with a remote object pointing to my secure destination:
sampleServiceRO = new RemoteObject("sampleService");
and created two buttons, one to execute sampleServiceRO.getName() and the other to execute sampleServiceRO.getSecureName(). Please note that I configured the RemoteObject manually instead of relying on specifying services-config.xml in the Flex compiler. Doing this is relatively easy:
var channel:AMFChannel = new AMFChannel();
channel.url = "http://localhost:8080/blazeds-spring/messagebroker/amf";
cs = new ChannelSet();
cs.addChannel(channel);
sampleServiceRO = new RemoteObject("sampleService");
sampleServiceRO.channelSet = cs;
Once all that’s setup and the servlet container is running, hit the non-secure method and you’ll get a reply. Hit the secure method and you’ll get a service fault, as you should, because you’re not logged in. Next hit an url that requires the ROLE_ADMIN and log in when the BasicAuth box pops up. Now hit the secure method again and you should get a response.
There’s are some issues that I see here:
1) If you’re using BasicAuth and you hit a secured destination you won’t get the BasicAuth dialog box automatically, you have to go to a URL, get the box, then hit the original method again.
2) You’re bypassing LoginCommand and the BlazeDS security model. I’m not completely sure if this is wise. For example, what happens when I use DataService destinations with RTMP? When does authentication happen?
3) You can’t pass credentials with setCredentials or setRemoteCredentials. You have to log in some other way.
I’d like to hear how others have handled this.
July 6th, 2008 at 4:01 pm
[...] and Spring Security http://www.machine501.com/blog/2008/02/14/blazeds-and-spring-security/ http://www.machine501.com/blog/2008/05/30/blazeds-spring-and-acegi-security-part-2/ [...]
May 20th, 2009 at 11:46 am
[...] machine501 » Blog Archive » BlazeDS and Spring Security (tags: blazeds security) [...]
May 29th, 2009 at 9:08 am
May be my example of BlazeDS and Spring Security integration will be useful to someone, see http://dima-vp.livejournal.com/573.html.