Autenticación en aplicaciones Flex con Spring Security 3


Spring Security es un framework que se centra en proveer mecanismos de autenticación y autorización para aplicaciones basadas en Spring. Mediante el paquete de integración de Spring con BlazeDS spring-flex, conjuntamente con Spring Security, podemos añadir seguridad a nuestras aplicaciones Flex/BlazeDS.

En este artículo veremos, a través de un ejemplo, cómo podemos utilizar el mecanismo de autenticación de Spring Security desde una aplicación Flex. En la aplicación que desarrollaremos tenemos la información de los usuarios y los roles asignados a éstos en una base de datos MySQL, a la cual accederemos utilizando JPA e Hibernate. Desde Flex invocaremos el servicio de autenticación de Spring Security, el cual utilizará la información de los usuarios y roles en la base de datos para comprobar las credenciales de usuario suministradas, si el proceso termina exitosamente tendremos en la aplicación Flex la información del usuario autenticado, en caso contrario se nos notificará del error.

Para el desarrollo de la aplicación utilizaremos:

  • Spring 3.0.2
  • Spring Security 3.0.3
  • Spring-Flex 1.5.0.M1
  • BlazeDS 4.0.0.14931
  • Flex 4
  • Flash Builder 4 plugin en Eclipse IDE for J2EE (Galileo)
  • RobotLegs 1.1.2

La aplicación la desarrollaremos en dos proyectos, un proyecto Web J2EE para el back-end y un proyecto Flex para la interface visual.

El back-end

Comenzaremos por la creación del proyecto Web J2EE

  1. File … Import … Web->War File
  2. WAR File: El camino del archivo blazeds.war
  3. Web Project: FlexSpringSecurity
  4. Target Runtime: Alguno que se haya configurado previamente
  5. War Import: Web Libraries. No seleccionamos ningún paquete

Copiamos en la carpeta WebContent\WEB-INF\lib los archivos de Spring, Spring Security, Spring-Flex, el driver JDBC de MySQL. El listado de los archivos de la carpeta se puede ver aquí.

Como utilizamos el paquete de integración de Spring con BlazeDS solamente necesitamos en la carpeta WebContent\WEB-INF\flex el archivo services-config.xml. También necesitamos modificar el archivo web.xml en WebContent\WEB-INF, en el que se hace referencia a los archivos web-application-config.xml y web-application-context-config.xml, donde se configura el contexto de Spring.

Comenzaremos por crear la capa que accederá a la base de datos para obtener la información de usuarios y roles.

User.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.valueobject;
  2.  
  3. import java.util.List;
  4.  
  5. import javax.persistence.CascadeType;
  6. import javax.persistence.Entity;
  7. import javax.persistence.FetchType;
  8. import javax.persistence.GeneratedValue;
  9. import javax.persistence.Id;
  10. import javax.persistence.ManyToMany;
  11.  
  12. public class User {
  13.  
  14.     private Long id;
  15.     private String fullName;
  16.     private String userName;
  17.     private String password;
  18.  
  19.     @Id
  20.     @GeneratedValue
  21.     public Long getId() {
  22.         return id;
  23.     }
  24.  
  25.     public void setId(Long id) {
  26.         this.id = id;
  27.     }
  28.  
  29.     public String getFullName() {
  30.         return fullName;
  31.     }
  32.  
  33.     public void setFullName(String fullName) {
  34.         this.fullName = fullName;
  35.     }
  36.  
  37.     public String getUserName() {
  38.         return userName;
  39.     }
  40.  
  41.     public void setUserName(String userName) {
  42.         this.userName = userName;
  43.     }
  44.  
  45.     public String getPassword() {
  46.         return password;
  47.     }
  48.  
  49.     public void setPassword(String password) {
  50.         this.password = password;
  51.     }
  52.    
  53.     private List<Role> roleList;
  54.  
  55.     @ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
  56.     public List<Role> getRoleList() {
  57.         return roleList;
  58.     }
  59.  
  60.     public void setRoleList(List<Role> roleList) {
  61.         this.roleList = roleList;
  62.     }
  63. }

Role.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.valueobject;
  2.  
  3. import javax.persistence.Entity;
  4. import javax.persistence.GeneratedValue;
  5. import javax.persistence.Id;
  6.  
  7. public class Role {
  8.  
  9.     private Long id;
  10.     private String name;
  11.  
  12.     @Id
  13.     @GeneratedValue
  14.     public Long getId() {
  15.         return id;
  16.     }
  17.  
  18.     public void setId(Long id) {
  19.         this.id = id;
  20.     }
  21.  
  22.     public String getName() {
  23.         return name;
  24.     }
  25.  
  26.     public void setName(String name) {
  27.         this.name = name;
  28.     }
  29. }

RoleType.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.valueobject;
  2.  
  3. public class RoleType {
  4.     public static final String ADMIN = "ADMINISTRATOR";
  5.     public static final String USER = "USER";
  6.     public static final String GEST = "GEST";
  7. }

IUserService.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.service;
  2.  
  3. import java.util.List;
  4. import com.nonocarballo.flexspringsecurity.valueobject.User;
  5.  
  6. public interface IUserService {
  7.     public List<User> loadAllUsers();
  8.     public void addUser(User user);
  9.     public User loabByUserName(String username);
  10. }

UserService.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.service.impl;
  2.  
  3. import java.util.List;
  4. import javax.persistence.EntityManager;
  5. import javax.persistence.PersistenceContext;
  6. import javax.persistence.PersistenceContextType;
  7. import javax.persistence.Query;
  8.  
  9. import org.springframework.flex.remoting.RemotingDestination;
  10. import org.springframework.flex.remoting.RemotingExclude;
  11. import org.springframework.stereotype.Repository;
  12. import org.springframework.transaction.annotation.Transactional;
  13.  
  14. import com.nonocarballo.flexspringsecurity.service.IUserService;
  15. import com.nonocarballo.flexspringsecurity.valueobject.User;
  16.  
  17. @RemotingDestination
  18. public class UserService implements IUserService {
  19.  
  20.     private EntityManager entityManager;
  21.    
  22.     @RemotingExclude
  23.     public EntityManager getEntityManager() {
  24.         return entityManager;
  25.     }
  26.  
  27.     @RemotingExclude
  28.     @PersistenceContext(type = PersistenceContextType.EXTENDED)
  29.     public void setEntityManager(EntityManager entityManager) {
  30.         this.entityManager = entityManager;
  31.     }
  32.  
  33.     @SuppressWarnings("unchecked")
  34.     @Override
  35.     public List<User> loadAllUsers() {
  36.         // TODO Auto-generated method stub
  37.         return entityManager.createQuery("from User u").getResultList();
  38.     }
  39.  
  40.     @Override
  41.     @Transactional
  42.     public User loabByUserName(String username) {
  43.         Query userQuery = entityManager.createQuery("from User u where u.userName = :user");
  44.         userQuery.setParameter("user", username);
  45.         User user = (User) userQuery.getSingleResult();
  46.         return user;
  47.     }
  48.  
  49.     @Override
  50.     @Transactional
  51.     public void addUser(User user) {
  52.         // TODO Auto-generated method stub
  53.         entityManager.persist(user);       
  54.     }
  55. }

Escribimos ahora un código en forma de test para generar las tablas de la base de datos y llenarlas con alguna información.

UserServiceTest.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.test;
  2.  
  3. import static org.junit.Assert.*;
  4.  
  5. import java.util.ArrayList;
  6.  
  7. import org.junit.Test;
  8. import org.junit.runner.RunWith;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.test.context.ContextConfiguration;
  11. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  12.  
  13. import com.nonocarballo.flexspringsecurity.service.IUserService;
  14. import com.nonocarballo.flexspringsecurity.valueobject.Role;
  15. import com.nonocarballo.flexspringsecurity.valueobject.RoleType;
  16. import com.nonocarballo.flexspringsecurity.valueobject.User;
  17.  
  18. @RunWith(SpringJUnit4ClassRunner.class)
  19. @ContextConfiguration(locations={"classpath:/spring/web-application-context-config.xml"})
  20. public class UserServiceTest {
  21.  
  22.     private IUserService userService;
  23.  
  24.     public IUserService getUserService() {
  25.         return userService;
  26.     }
  27.  
  28.     @Autowired
  29.     public void setUserService(IUserService userService) {
  30.         this.userService = userService;
  31.     }
  32.    
  33.     @Test
  34.     public void addUserTest(){
  35.        
  36.         User user = new User();
  37.         user.setFullName("Nono Carballo Escalona");
  38.         user.setUserName("nono");
  39.         user.setPassword("mypassword");
  40.        
  41.         ArrayList<Role> roleList = new ArrayList<Role>();
  42.        
  43.         Role role = new Role();  
  44.         role.setName(RoleType.GEST);
  45.         roleList.add(role);
  46.        
  47.         role = new Role();   
  48.         role.setName(RoleType.USER);
  49.         roleList.add(role);
  50.        
  51.         role = new Role();   
  52.         role.setName(RoleType.ADMIN);
  53.         roleList.add(role);
  54.        
  55.         user.setRoleList(roleList);
  56.        
  57.         userService.addUser(user);
  58.        
  59.         user = new User();
  60.         user.setFullName("Nono Carballo Escalona1");
  61.         user.setUserName("nono1");
  62.         user.setPassword("mypassword1");
  63.        
  64.         roleList = new ArrayList<Role>();
  65.        
  66.         role = new Role();   
  67.         role.setName(RoleType.GEST);
  68.         roleList.add(role);
  69.        
  70.         user.setRoleList(roleList);
  71.        
  72.         userService.addUser(user);
  73.        
  74.         user = new User();
  75.         user.setFullName("Nono Carballo Escalona2");
  76.         user.setUserName("nono2");
  77.         user.setPassword("mypassword2");
  78.        
  79.         roleList = new ArrayList<Role>();
  80.        
  81.         role = new Role();   
  82.         role.setName(RoleType.USER);
  83.         roleList.add(role);
  84.        
  85.         user.setRoleList(roleList);
  86.        
  87.         userService.addUser(user);
  88.        
  89.         ArrayList<User> userList = (ArrayList<User>) userService.loadAllUsers();
  90.        
  91.         assertTrue(userList.size() == 3);
  92.        
  93.     }
  94. }

Para la interacción entre spring-flex y Spring Security debe registrarse en el archivo web.xml el un filtro del tipo DelegatingFilterProxy.

XML:
  1. <filter>
  2.         <filter-name>springSecurityFilterChain</filter-name>
  3.         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. </filter>
  5.    
  6. <filter-mapping>
  7.         <filter-name>springSecurityFilterChain</filter-name>
  8.         <url-pattern>/*</url-pattern>
  9. </filter-mapping>

Debemos crear una clase a través de la cual Spring Security recuperará de la base de datos la información del usuario que intenta autenticarse. Esta clase implementará la interface UserDetailsService, que tiene un único método, loadUserByUsername, el cual será invocado por el proveedor de autenticación del framework.

MyUserDetailsService.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.service;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. import org.apache.commons.logging.Log;
  7. import org.apache.commons.logging.LogFactory;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.dao.DataAccessException;
  10. import org.springframework.security.core.GrantedAuthority;
  11. import org.springframework.security.core.authority.GrantedAuthorityImpl;
  12. import org.springframework.security.core.userdetails.UserDetails;
  13. import org.springframework.security.core.userdetails.UserDetailsService;
  14. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  15. import org.springframework.stereotype.Repository;
  16. import org.springframework.transaction.annotation.Transactional;
  17.  
  18. import com.nonocarballo.flexspringsecurity.valueobject.AuthenticatedUser;
  19. import com.nonocarballo.flexspringsecurity.valueobject.Role;
  20. import com.nonocarballo.flexspringsecurity.valueobject.User;
  21.  
  22. public class MyUserDetailsService implements UserDetailsService {
  23.    
  24.     private IUserService userService;
  25.  
  26.     public IUserService getUserService() {
  27.         return userService;
  28.     }
  29.  
  30.     @Autowired
  31.     public void setUserService(IUserService userService) {
  32.         this.userService = userService;
  33.     }
  34.  
  35.     @Override
  36.     @Transactional
  37.     public UserDetails loadUserByUsername(String arg0)
  38.             throws UsernameNotFoundException, DataAccessException {
  39.         User user = userService.loabByUserName(arg0);
  40.         if(user == null){
  41.             throw new
  42. UsernameNotFoundException("User "+arg0+" not found.");
  43.         }
  44.         List<Role> roleList=(List<Role>) user.getRoleList();
  45.         ArrayList<GrantedAuthority> grantedAuthorities = new
  46.  ArrayList<GrantedAuthority>();
  47.         for(Role role : roleList){
  48.             grantedAuthorities.add(new GrantedAuthorityImpl(role.getName()));
  49.         }
  50.         return new
  51.  org.springframework.security.core.userdetails.User(user.getUserName(),
  52.                 user.getPassword(), true, true, true, true, grantedAuthorities);
  53.        
  54.     }
  55. }

El objeto de tipo org.springframework.security.core.userdetails.User contiene la información que llegará a la aplicación Flex, en este caso el nombre de usuario y los roles que tiene asignados.

Ahora debemos informar a Spring Security que use nuestra clase y no la que trae el framework, esto se hace en el archivo web-application-context-config.xml, la configuración final queda como sigue:

XML:
  1. <security:http entry-point-ref="entryPoint">
  2.  <security:anonymous enabled="false"/>
  3.  </security:http>
  4.    
  5.  <bean id="entryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
  6.  
  7. <security:authentication-manager>
  8.     <security:authentication-provider user-service-ref="myUserDetailsService"/>
  9. </security:authentication-manager>

Y finalmente de debemos informar a spring-flex (en el archivo web-application-config.xml) que utilice el servicio de autenticación de Spring Security.

XML:
  1. <flex:message-broker>   
  2.     <flex:secured />
  3. </flex:message-broker>

La aplicación Flex

Crearemos un proyecto Flex que llamaremos FlexSpringSecurityUI con las siguientes características:

  • Application Type: Web
  • Flex SDK Version: Flex 4.0
  • Application Server Type: J2EE
  • Remote access service: BlazeDS
  • RootFolder: el camino a la carpeta FlexSecurity/WebContent
  • Root URL: el URL donde se desplegó el proyecto FlexSpringSecurity
  • Context root: flexspringsecurity

Nuestra aplicación Flex contendrá un formulario para autenticación y un botón para entrar (login) y salir (logout).

login

Crearemos un objeto de tipo ChannelSet y le adicionaremos un canal de tipo AMFChannel, luego para invocar al servicio de autenticación de Spring Security desde Flex utilizaremos el método login de lal objeto ChannelSet, lo invocaremos pasándole como argumentos el nombre de usuario y la contraseña introducidos en el formulario. En esta aplicación recuperaremos el URL donde está desplegado el back-end en tiempo de ejecución, desde un archivo xml, y utilizaremos esa información para crear programáticamente el canal e insertarlo en el ChannelSet. Nos auxiliaremos del framework Robotlegs.

channels.xml

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <channels>
  3.     <channel type="amf">
  4.         <uri>http://localhost:8080/flexspringsecurity</uri>
  5.     </channel>
  6.     <channel type="secure-amf">
  7.         <uri>https://localhost:8080/flexspringsecurity</uri>
  8.     </channel>
  9. </channels>

Actionscript 3:
  1. package com.nonocarballo.flexspringsecurity.command
  2. {
  3.     import mx.messaging.ChannelSet;
  4.     import mx.messaging.channels.AMFChannel;
  5.     import mx.rpc.CallResponder;
  6.     import mx.rpc.events.ResultEvent;
  7.     import mx.rpc.http.HTTPService;
  8.    
  9.     import org.robotlegs.mvcs.Command;
  10.    
  11.     public class LoadConfigCommand extends Command
  12.     {
  13.         public function LoadConfigCommand()
  14.         {
  15.             super();
  16.         }
  17.        
  18.         private var responder:CallResponder = new CallResponder();
  19.        
  20.         override public function execute():void{
  21.             var service:HTTPService = new HTTPService();
  22.             service.url = "config/channels.xml";
  23.             service.resultFormat = "e4x";
  24.            
  25.             responder.addEventListener(ResultEvent.RESULT, resultHandler);
  26.             responder.token = service.send();
  27.         }
  28.        
  29.         private function resultHandler(event: ResultEvent):void{
  30.             var xml:XML = event.result as XML;
  31.            
  32.             var channelSet:ChannelSet = new ChannelSet();
  33.             for each(var item:XML in xml..channel){
  34.                 if(item.@type=="amf"){
  35.                     var amfChannel:AMFChannel = new AMFChannel();
  36.                     amfChannel.uri = item.uri+"/messagebroker/amf";
  37.                     channelSet.addChannel(amfChannel);
  38.                     break;
  39.                 }
  40.             }
  41.             injector.mapValue(ChannelSet, channelSet);
  42.         }
  43.     }
  44. }

Cuando presionamos el botón “Entrar” invocamos el método login del objeto ChannelSet con la credencial del usuario:

Actionscript 3:
  1. package com.nonocarballo.flexspringsecurity.command
  2. {
  3.     import com.nonocarballo.flexspringsecurity.event.AuthenticatedEvent;
  4.     import com.nonocarballo.flexspringsecurity.event.LoginEvent;
  5.    
  6.     import flash.events.Event;
  7.    
  8.     import mx.messaging.ChannelSet;
  9.     import mx.rpc.CallResponder;
  10.     import mx.rpc.events.FaultEvent;
  11.     import mx.rpc.events.ResultEvent;
  12.    
  13.     import org.robotlegs.mvcs.Command;
  14.    
  15.     public class LoginCommand extends Command
  16.     {
  17.         public function LoginCommand()
  18.         {
  19.             super();
  20.         }
  21.        
  22.         [Inject]
  23.         public var channelSet:ChannelSet;
  24.        
  25.         [Inject]
  26.         public var event:LoginEvent;
  27.        
  28.         private var responder:CallResponder = new CallResponder();
  29.        
  30.         override public function execute():void{
  31.             if(!channelSet.authenticated){
  32.                 responder.addEventListener(ResultEvent.RESULT, resultHandler);
  33.                 responder.addEventListener(FaultEvent.FAULT, faultHandler);
  34.                 responder.token = channelSet.login(event.username,
  35. event.password);
  36.             }
  37.         }
  38.        
  39.         private function resultHandler(event:ResultEvent):void{
  40.             dispatch(new AuthenticatedEvent(AuthenticatedEvent.AUTHENTICATED,
  41. event.result));
  42.         }
  43.        
  44.         private function faultHandler(event:FaultEvent):void{
  45.             dispatch(new AuthenticatedEvent(AuthenticatedEvent.LOGIN_FAILURE));
  46.         }
  47.     }
  48. }

Si la credencial de usuario no es válida obtendremos:

login-fail

En caso contrario:

login-ok-pre

Más información del usuario en Flex

Con el objeto org.springframework.security.core.userdetails.User solo obtenemos información del nombre de usuario y los roles, pero casi nunca esa información es suficiente. Haremos los cambios necesarios para poder traer hacia la aplicación Flex información extra del usuario que se ha autenticado.

Primeramente debemos crear nuestra propia implementación de UserDetails y añadir toda la información que necesitemos, en nuestro caso solo añadimos el nombre completo del usuario (fullname).

AuthenticatedUser.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.valueobject;
  2.  
  3. import java.util.Collection;
  4.  
  5. import org.springframework.security.core.GrantedAuthority;
  6. import org.springframework.security.core.userdetails.UserDetails;
  7.  
  8. @SuppressWarnings("serial")
  9. public class AuthenticatedUser implements UserDetails {
  10.  
  11.     private String username;
  12.     private String password;
  13.     private String fullname;
  14.    
  15.    
  16.     public String getFullname() {
  17.         return fullname;
  18.     }
  19.  
  20.     private Collection<GrantedAuthority> authorities;
  21.    
  22.     @Override
  23.     public Collection<GrantedAuthority> getAuthorities() {
  24.         // TODO Auto-generated method stub
  25.         return authorities;
  26.     }
  27.  
  28.     @Override
  29.     public String getPassword() {
  30.         // TODO Auto-generated method stub
  31.         return password;
  32.     }
  33.  
  34.     @Override
  35.     public String getUsername() {
  36.         // TODO Auto-generated method stub
  37.         return username;
  38.     }
  39.  
  40.     @Override
  41.     public boolean isAccountNonExpired() {
  42.         // TODO Auto-generated method stub
  43.         return true;
  44.     }
  45.  
  46.     @Override
  47.     public boolean isAccountNonLocked() {
  48.         // TODO Auto-generated method stub
  49.         return true;
  50.     }
  51.  
  52.     @Override
  53.     public boolean isCredentialsNonExpired() {
  54.         // TODO Auto-generated method stub
  55.         return true;
  56.     }
  57.  
  58.     @Override
  59.     public boolean isEnabled() {
  60.         // TODO Auto-generated method stub
  61.         return true;
  62.     }
  63.  
  64.     public AuthenticatedUser() {
  65.         super();
  66.         // TODO Auto-generated constructor stub
  67.     }
  68.  
  69.     public AuthenticatedUser(String username, String fullname, String password,
  70.             Collection<GrantedAuthority> authorities) {
  71.         super();
  72.         this.username = username;
  73.         this.fullname = fullname;
  74.         this.password = password;
  75.         this.authorities = authorities;
  76.     }
  77. }

Luego necesitamos crear nuestro propio interceptor de mensaje implementando MessageInterceptor. Esta clase es la encargada de extraer del resultado del proceso de autenticación la información que llegará a la aplicación Flex una vez concluido éste exitosamente.

MyLoginMessageInterceptor.java

JAVA:
  1. package com.nonocarballo.flexspringsecurity.service;
  2.  
  3. import org.apache.commons.logging.Log;
  4. import org.apache.commons.logging.LogFactory;
  5. import org.springframework.flex.core.MessageInterceptor;
  6. import org.springframework.flex.core.MessageProcessingContext;
  7. import org.springframework.stereotype.Service;
  8.  
  9. import flex.messaging.messages.CommandMessage;
  10. import flex.messaging.messages.Message;
  11.  
  12. @Service
  13. public class MyLoginMessageInterceptor implements MessageInterceptor {
  14.  
  15.     private final Log logger = LogFactory.getLog(getClass());
  16.     
  17.     @Override
  18. public Message postProcess(MessageProcessingContext context, Message inputMessage,
  19.             Message outputMessage) {
  20.         // TODO Auto-generated method stub
  21.         if (inputMessage instanceof CommandMessage &&
  22. ((CommandMessage) inputMessage).getOperation() ==
  23. CommandMessage.LOGIN_OPERATION) {
  24.             if (outputMessage.getBody()!= null) {
  25.                 outputMessage.setBody(
  26. MyAuthenticationResultUtils.getAuthenticationResult());
  27. }
  28. }
  29. return outputMessage;
  30.     }
  31.  
  32.     @Override
  33.     public Message preProcess(MessageProcessingContext context, Message inputMessage) {
  34.         // TODO Auto-generated method stub
  35.         return inputMessage;
  36.     }
  37.  
  38. }

Como vemos, esta clase hace uso de MyAuthenticationResultUtils, la cual crearemos también, y donde ocurre la creación del objeto que llegará a la aplicación Flex en la propiedad result de la clase ResultEvent.

JAVA:
  1. package com.nonocarballo.flexspringsecurity.service;
  2.  
  3. import java.util.HashMap;
  4. import java.util.Map;
  5.  
  6. import org.springframework.security.core.Authentication;
  7. import org.springframework.security.core.GrantedAuthority;
  8. import org.springframework.security.core.context.SecurityContextHolder;
  9.  
  10. import com.nonocarballo.flexspringsecurity.valueobject.AuthenticatedUser;
  11.  
  12. public abstract class MyAuthenticationResultUtils {
  13.  
  14.     public static Map<String, Object> getAuthenticationResult() {
  15.         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  16.         if (authentication == null) {
  17.             return null;
  18.         }
  19.         Map<String, Object> authenticationResult = new HashMap<String, Object>();
  20.         authenticationResult.put("name", authentication.getName());
  21.         String[] authorities = new String[authentication.getAuthorities().size()];
  22.         int i=0;
  23.         for (GrantedAuthority granted : authentication.getAuthorities()) {
  24.             authorities[i++] = granted.getAuthority();
  25.         }
  26.         authenticationResult.put("authorities", authorities);
  27.         authenticationResult.put("fullname", ((AuthenticatedUser)authentication.getPrincipal()).getFullname());
  28.         return authenticationResult;
  29.     }
  30. }

Finalmente debemos registrar nuestro interceptor de mensaje personalizado:

XML:
  1. <flex:message-broker>
  2.         <flex:message-interceptor ref="myLoginMessageInterceptor"/>
  3.         <flex:secured />
  4. </flex:message-broker>

Cuando nos autenticamos nuevamente obtenemos:

login-ok

El código fuente de los proyectos se puede descargar aquí.

Conclusiones

Spring Security provee un mecanismo flexible de autenticación (y control de acceso) para aplicaciones basadas en Spring. En nuestra aplicación de ejemplo utilizamos JPA e Hibernate para acceder a la información de los usuarios.

Utilizando el paquete de integración de Spring con BlazeDS y Spring Security podemos implementar mecanismos de autenticación en nuestras aplicaciones Flex/BlazeDS.

Comparte:



8votos  Vota!!

Acerca de esta entrada