PDA

View Full Version : Extracting UserDetails in Flex client



buzo
Mar 30th, 2009, 09:21 PM
Hi there:

I have a Flex project that is successfully authenticating users using spring-security via spring-blazeds integration. For completeness sake, my backend is configured as follows:

spring-flex.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans>
<import resource="classpath:core/main-context.xml" />

<flex:message-broker>
<flex:secured />
</flex:message-broker>

<bean id="userService" class="com.mymodules.security.service.spring.UserServiceI mpl">
<constructor-arg ref="userDao" />
<flex:remote-service />
</bean>
</beans>

spring-security.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans>
<http auto-config="true" session-fixation-protection="none"/>

<authentication-provider user-service-ref='userService'/>

</beans>

The above “userService” bean is an instance of my custom class, UserServiceImpl, which implements the interface org.springframework.security.userdetails.UserDetai lsService:


UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException;

As most of you probably know, UserDetails contains the various roles associated with a user: these can be retrieved via the UserDetails.getAuthorities() method.

For blazeDs configuration I have:

WEB-INF/flex/services-config.xml


<?xml version="1.0" encoding="UTF-8"?>
<services-config>

<services>
<default-channels>
<channel ref="my-amf" />
</default-channels>
</services>

<channels>
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint" />
<properties>
<polling-enabled>false</polling-enabled>
</properties>
</channel-definition>
</channels>

</services-config>

Now, on the front-end, I have an ActionScript UserDelagate.as class which performs login/logout via a ChannelSet; the relavant snippet:


public function UserDelegate( channelSet:ChannelSet )
{
this.service = channelSet;
this.service.addEventListener( ResultEvent.RESULT, onSuccess );
this.service.addEventListener( FaultEvent.FAULT, onFailure );
}


public function login( username:String, password:String ):void {

service.login( username, password );

}

public function logout():void {

service.logout();
}

Finally, on the clien-side, I inject the ChannelSet into the UserDelegate via spring-actionscript:

spring-client.xml


<?xml version="1.0" encoding="utf-8"?>
<objects>

<property file="properties.config" />


<!-- Remote Services -->

<object id="channelSet" class="mx.messaging.ChannelSet">
<method-invocation name="addChannel">
<arg>
<object id="amfChannel" class="mx.messaging.channels.AMFChannel">
<property name="url"
value="http://${host}:${port}/${context-root}/messagebroker/amf" />
</object>
</arg>
</method-invocation>
</object>

<!-- Business Delegates -->

<object id="delegateLocator" class="hc.control.delegates.DelegateLocator" factory-method="getInstance" >
<property name="userDelegate">
<object class="hc.control.delegates.UserDelegate" >
<constructor-arg ref="channelSet"/>
</object>
</property>
</object>

</objects>

This is all presently working. Now, what I'd like to do is to extract the user roles from the UserDetails object resulting from the invocation of the UserService.loadUserByUsername method on the backend (which gets triggered by the UserDelegate.login method in the flex client). Can this be done in a single call? I'd like to avoid having to perform two distinct invocations (one for login and one for userService) every time the user logs in.

Any help or ideas is greatly appreciated.

Thanks in advanced.

jeremyg484
Mar 31st, 2009, 08:45 AM
Hmmm...this is somewhat a limitation of the BlazeDS AuthenticationService in that it just returns a "success" message on successful login, and that's what gets encoded into the "result" property of the ResultEvent on the client side.

That said, we are already intercepting the message dispatch using AOP, so we could perhaps inject some more useful information into the result. Do you think making the GrantedAuthority[] from UserDetails available in the ResultEvent would be sufficient? If we implement this, we would probably make it a feature that you have to explicitly turn on with a flag in the <flex:secured> tag.

buzo
Mar 31st, 2009, 02:48 PM
That said, we are already intercepting the message dispatch using AOP, so we could perhaps inject some more useful information into the result. Do you think making the GrantedAuthority[] from UserDetails available in the ResultEvent would be sufficient? If we implement this, we would probably make it a feature that you have to explicitly turn on with a flag in the <flex:secured> tag.

This would be perfect. Having the user roles (ie GrantedAuthority[]) available in the ResultEvent would allow the flex client to determine the target transition state from the login screen: a regular user would be presented with a different set of screens than an admin user.

Let me know if this doable and how can I be notified once this feature is added.

Thanks in advanced

Antoine Véret
Apr 2nd, 2009, 06:35 AM
Great, i also need this feature

In order to be notified, watch the FLEX-35 Jira issue

anandintouch
Apr 21st, 2009, 01:37 AM
Hi Jeremy ,
I just wanted to know how to do database authentication using flex-blazeds-spring security. I'm trying to use UserDetailsService implmented by my custom class.I have one User domain class which implements Userdetails interface.
When I'm trying to run the application I get "Null pointer exception". It's failing to find the AuthenticationManager refernce.
AuthenticationManager manager = (AuthenticationManager)appContext.getBean("_authenticationManager");
manager is null here ,I'm not sure where exactly this "_authenticationManager" is mapped .
I'm using same code base but using database authentication instead of In memory authentication done in "AuthenticationHelper.java" class
Help with java class and config file samples will be greatly appreciated. Error which i'm getting is mentioned below.
Thanks,
Anand
-------------------------------------------------------------------------------------
23:39:44,359 DEBUG FilterChainProxy:355 - /messagebroker/amf reached end of addi
tional filter chain; proceeding with original chain
[BlazeDS]Channel endpoint my-amf received request.
[BlazeDS]Deserializing AMF/HTTP request
Version: 3
(Message #0 targetURI=null, responseURI=/2)
(Array #0)
[0] = (Typed Object #0 'flex.messaging.messages.RemotingMessage')
source = null
operation = "authenticatePrincipal"
body = (Array #1)
[0] = "9999"
[1] = "555DP"
messageId = "517742BA-F99B-F173-4856-C766CBED8B2F"
clientId = null
timeToLive = 0
timestamp = 0
headers = (Object #2)
DSId = "6D1F9A62-809A-B6A5-1300-06878BE44FEA"
DSEndpoint = "my-amf"
destination = "authenticationHelper"

23:39:44,375 DEBUG DefaultListableBeanFactory:214 - Returning cached instance of
singleton bean '_authenticationManager'
23:39:44,375 DEBUG ProviderManager:190 - Authentication attempt using org.spring
framework.security.providers.dao.DaoAuthentication Provider
23:39:44,390 DEBUG SharedEntityManagerCreator$SharedEntityManagerInvo cationHandl
er:185 - Creating new EntityManager for shared EntityManager invocation
23:39:44,484 DEBUG EntityManagerFactoryUtils:311 - Closing JPA EntityManager
[BlazeDS]Serializing AMF/HTTP response
Version: 3
(Message #0 targetURI=/2/onStatus, responseURI=)
(Typed Object #0 'flex.messaging.messages.ErrorMessage')
headers = (Object #1)
rootCause = (Typed Object #2 'java.lang.NullPointerException')
message = null
localizedMessage = null
cause = null
body = null
correlationId = "517742BA-F99B-F173-4856-C766CBED8B2F"
faultDetail = null
faultString = "java.lang.NullPointerException : null"
clientId = "6D1FA670-70E6-337C-5252-96562BAD4F36"
timeToLive = 0.0
destination = "authenticationHelper"
timestamp = 1.2402959845E12
extendedData = null
faultCode = "Server.Processing"
messageId = "6D1FB983-4086-745D-C4E1-2FBD2919B59B"

23:39:44,500 DEBUG ExceptionTranslationFilter:104 - Chain processed normally
--------------------------------------------------------------------------------------

jeremyg484
Apr 21st, 2009, 08:23 AM
I just wanted to know how to do database authentication using flex-blazeds-spring security.


So from your posted log, it looks like you are trying to call your authentication logic directly via RPC. Why not use ChannelSet.login()? If you have Spring Security configured properly, your custom user details service should get called.