Spring Security integration is enabled through the secured
child element of the message-broker
tag. The
simplest possible configuration would be:
<flex:message-broker> <flex:secured /> </flex:message-broker>
This enables the basic security features. A special BlazeDS LoginCommand
implementation is automatically installed that
enables ChannelSet.login and ChannelSet.logout requests to integrate with Spring Security's Authorization mechanisms. Additionally,
the special LoginCommand
enables Spring Security granted authorities to be referenced in BlazeDS XML security constraints.
For example, if we were using a traditional BlazeDS remoting destination defined in remoting-config.xml, we could have something like
the following:
<destination id="productService"> ... <security> <security-constraint> <auth-method>Custom</auth-method> <roles> <role>ROLE_USER</role> </roles> </security-constraint> </security> </destination>
As you can see, we are referencing the "ROLE_USER" authority from our simple Spring Security setup. The invocation of this remote
destination would cause the provided LoginCommand
to be invoked to both verify that the user is logged in and to check
that they have the appropriate role. Violation of either will result in an exception being thrown by Spring Security.
When using the ChannelSet.login API call from the Flex client with Spring Security integration enabled, the resulting ResponseEvent fired client-side upon successful completion will contain additional information that can be inspected about the current user. The name and authorities will be extracted from the Authentication object and added to the body of the response message. This information, for example, can then be used to conditionally display different portions of the UI based on the user's identity and granted roles:
var token:AsyncToken = myChannelSet.login("jeremy","atlanta"); token.addResponder( new AsyncResponder( function(event:ResultEvent, token:Object = null):void { if (event.result.authorities.indexOf("ROLE_ADMIN") >= 0) { displayAdminPanel(event.result.name); } else { displayUserPanel(event.result.name); } }, function(event:FaultEvent, token:Object = null):void { displayErrorMessage("Login Failed: "+event.fault.faultString); } ) );
Another feature that is automatically installed when the secured
tag is used is automatic exception translation from
any thrown SpringSecurityException to the proper BlazeDS SecurityException. The exceptions are caught and translated at the proper
point in the execution chain such that it will result in the proper AMF error message being serialized and sent back to the client.
This is alternative to the normal Spring Security behavior where a filter in the chain catches the exception and sends back a
corresponding HTTP status code. The problem with sending back HTTP status codes other than 200 is that this causes the Flex client
to throw a generic and rather unhelpful exception, and often the status code can't be determined from the Flex client. Sending back
specific AMF error messages instead causes a FaultEvent
to be thrown client-side that contains the proper
security fault code that can then be reasoned on and appropriate action can be taken. This behavior is equivalent to that of the
out-of-the-box container-based security mechanisms provided with BlazeDS, so the programming model client-side remains the same.
The secured
tag has several additional attributes that allow further customization.
If you are not using Spring Security's
default bean ids for the AuthenticationManager
or AccessDecisionManager
, you can specify your custom bean references
using the corresponding authentication-manager
and access-decision-manager
attributes respectively on the secured
tag.
The configuration of the provided LoginCommand
can be further controlled via the secured
tag. The invalidate-flex-session
attribute controls whether the current Flex session is invalidated when the logout()
method is called on the LoginCommand
, and
defaults to "true" if not specified. The per-client-authentication
attribute turns BlazeDS's per-client authentication mode on when true, and
defaults to "false" if not specified. Enabling per-client authentication will cause the Security context to no longer be stored in the session between
requests and thus will prevent the use of any Spring Security filters that rely on the Security Context being available in the session, but the authentication
and authorization integration will otherwise work as expected. (See the BlazeDS docs for further information on the difference between per-session and per-client
authentication.)