En este post intentaremos explicar de la forma más breve y clara como utilizar Spring Social en tu aplicación. Y como permitir logarse a los usuarios de una red social (en este caso Facebook), e incluso registrarlos en la aplicación, si es la primera vez que acceden.
El post se centrará exclusivamente en el funcionamiento de Spring Social (pudiendose explicar alguna otra sección si alguien lo pide). El código lo podéis encontrar aquí: Github.
- 1º paso: Obtener un ID para tu aplicación
Debemos acceder a Facebook Developers y crear una aplicación asociada a nuestro usuario. A esta aplicación le tenemos que dar permiso para autenticación con Facebook, y entre los datos a solicitar debemos pedirle el 'email'.
El identificador de facebook y su clave secreta se deben añadir al fichero application.properties (el fichero de configuración de Spring Boot).
- 2º paso: Indicar a Spring Security que vamos a hacer uso de Spring Social
Utilizaremos Spring Security para que maneje la autenticación de usuarios, y a que páginas se puede o no acceder. Con la siguiente configuración, permitiremos que los usuarios de redes sociales se integren dentro del ciclo de autenticación.
protected void configure( final HttpSecurity http ) throws Exception {http.authorizeRequests()
//... mas configuraciones aqui.and().apply( new SpringSocialConfigurer().postLoginUrl( "/" ).alwaysUsePostLoginUrl( true ) );}
- 3º paso: Configurar Spring Social
Debemos crear una clase que implemente 'SocialConfigurer'. Esta clase contendrá la anotación '@EnableSocial' que permitirá añadir esta configuración a la propia de Spring MVC. Además tendrá tres métodos esenciales.
- addConnectionFactories: No necesitaremos configurarlo al estar utilizando Spring Boot y haber configurado anteriormente el fichero 'application.properties' .
- getUserIdSource: Donde indicaremos que campo usaremos como identificador del usuario. La implementación por defecto que se suele hacer, nos permite indicar que será el 'username'. Esto nos dará algún quebradero de cabeza mas adelante, puesto que Facebook no cuenta con un username como tal.
- getUsersConnectionRepository: Donde indicaremos que la información de las conexiones será persistida en BBDD y que en caso de que el usuario no se haya logado nunca se redirija a un clase concreta (CustomConnectionSignUp) para registrarlo en la aplicación.
@Configuration @EnableSocial public class SocialConfig implements SocialConfigurer { @Autowired private DataSource dataSource; @Autowired private UserDao dao; @Override public void addConnectionFactories( final ConnectionFactoryConfigurer connectionFactoryConfigurer, final Environment environment ) { } @Override public UserIdSource getUserIdSource() { return new AuthenticationNameUserIdSource(); } @Override public UsersConnectionRepository getUsersConnectionRepository( final ConnectionFactoryLocator connectionFactoryLocator ) { JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository( dataSource, connectionFactoryLocator, Encryptors.noOpText() ); repository.setConnectionSignUp( new CustomConnectionSignUp( dao ) ); return repository; } }
La tabla donde se persitirán los datos es 'userconnection' y almacenará la información de conexión de los usuarios a través de sus redes sociales. Si encuentra al usuario en esta tabla, procederá a logarlo en la aplicación y en caso contrario procederá a registrarlo y posteriormente logarlo. El esquema de la misma se encuentra también en el código de Github.
- 4º Paso: Registrar usuario de red social automáticamente
Ya hemos configurado la clase que permite el registro, ahora nos queda implementarla. Básicamente nuestra labora será obtener los datos de Facebook, crear un registro del usuario de la aplicación con ellos y devolver el identificador de dicho usuario. Como ya indicamos anteriormente, un usuario de Facebook no tiene 'username' como tal, pero podemos utilizar su correo electrónico como identificador.
public class CustomConnectionSignUp implements ConnectionSignUp { private final UserDao userDao; public CustomConnectionSignUp( final UserDao usersDao ) { userDao = usersDao; } @Override public String execute( final Connection<?> connection ) { Facebook facebook = (Facebook) connection.getApi(); String[] fields = { "email", "name", "first_name", "last_name" }; User userProfile = facebook.fetchObject( "me", User.class, fields ); // seteamos a nulo para poder insertar AI MYSQL userProfile.setId( null ); // generamos password userProfile.setPassword( createEncryptPassword() ); // indicamos como username el correo userProfile.setUsername( userProfile.getEmail() ); userProfile = userDao.save( userProfile ); return userProfile.getEmail(); } private String createEncryptPassword() { return new BCryptPasswordEncoder().encode( RandomStringUtils.randomAlphanumeric( 17 ) ); } }
- 5º Paso: Identificar al usuario de la red social en la aplicación y logarlo
Deberemos crear una clase que implemente 'SocialUserDetailsService' y que permita logar al usuario proveniente de la red social. El parámetro 'userId' que llega al método 'loadUserByUserId', será el valor devuelto por la clase 'CustomConnectionSignUp'. Y el objeto UserDetails devuelto, será el asociado a la sesión del usuario a través de Spring Security.
El código de Github puede ser algo diferente, pero es porque para realizar esta parte nos hemos apoyado en 'UserDetailsService'. Y de paso nos sirve su implementación para realizar el acceso del usuario a través de usuario y contraseña.
El código de Github puede ser algo diferente, pero es porque para realizar esta parte nos hemos apoyado en 'UserDetailsService'. Y de paso nos sirve su implementación para realizar el acceso del usuario a través de usuario y contraseña.
@Service public class CustomSocialUsersDetailService implements SocialUserDetailsService { @Autowired private UserDao userDao; public UserDetails loadUserByUsername( final String username ) throws UsernameNotFoundException { User user = userDao.findByUsernameOrEmail( username, username ); if( user == null ) { throw new UsernameNotFoundException( "No user present with username/email: " + username ); } else { List<String> userRoles = new ArrayList<>(); userRoles.add( "USER" ); return new CustomUserDetails( user, userRoles ); } } @Override public SocialUserDetails loadUserByUserId( final String userId ) throws UsernameNotFoundException, DataAccessException { UserDetails userDetails = loadUserByUsername( userId ); return new SocialUser( userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities() ); } }
- 6º Paso: Habilitar enlace para logarse a través de Facebook
<form action="${pageContext.request.contextPath}/auth/facebook" method="POST"> <input type="hidden" name="scope" value="email, public_profile" /> <p><button class="btn btn-default col-md-12 col-sm-12 col-xs-12 btnSignFacebook" type="submit"><span class="fb-icon"></span><spring:message code="b.signFacebook" /></button></button></p> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> </form>
No hay comentarios:
Publicar un comentario