Seguridad en JavaFX con Spring Security (Parte-1)

Spring Security es un framework de seguridad, nos provee de mecanismos de autenticación y autorización, usualmente utilizado en la creación de aplicaciones web con Spring Framework, pero, en esta ocasión integraremos Spring Security a una aplicación JavaFX no web, veremos cómo crear un sistema de login y autorización por roles, además tendremos la posibilidad de proteger un método de una clase determinada.

Para empezar creamos una aplicación JavaFX, usaremos un proyecto tipo Maven creado a partir del archetype “javafx-basic-archetype”, usando IntelliJ IDEA Community Edition 15.0 creamos un nuevo proyecto de la siguiente manera:

javafx-basic-archetype
Editamos el archivo pom.xml y agregamos Spring Framework, para este ejemplo solo requerimos spring-context y Srping Security (spring-security-core, spring-security-config).

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>test</groupId>
    <artifactId>secure.javafx</artifactId>
    <name>securefx</name>

    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>

    <organization>
        <name>carmelo</name>
    </organization>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <build>
        <finalName>securefx</finalName>
        <plugins>
            <plugin>
                <groupId>com.zenjava</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>8.1.5</version>
                <configuration>
                    <mainClass>test.MainApp</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>

    </dependencies>

</project>

Ahora agregamos security.xml, este es el archivo de configuración para spring security, en el mismo definiremos el tipo de seguridad que usaremos, en este ejemplo habilitaremos la seguridad mediante anotación, específicamente @Secured y @PreAuthorize, además creamos un administrador de autenticación con grupo de usuarios preestablecidos memoria, si lo deseamos podemos obtener los usuarios de una base de datos.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/security
 http://www.springframework.org/schema/security/spring-security-4.0.xsd
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- habilitar uso de @Secured y @PreAuthorized -->
    <security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/>

    <!-- crear un proveedor de autenticacion con 2 usuarios en memoria -->
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="user1" password="123" authorities="ROLE_ADMIN"/>
                <security:user name="user2" password="456" authorities="ROLE_USER, ROLE_STANDAR"/>
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>

</beans>

Creamos una aplicación Spring configurada con Java, para obtener más información puedes ver: IoC con Spring Framework, debemos combinar la configuración Java con XML, para ello usaremos la anotación @ImportResource("classpath:security.xml"), lo siguiente que haremos será iniciar el contexto de seguridad, establecemos a MODE_GLOBAL para utilizar un único contexto de seguridad para toda la aplicación ya solo habrá un usuario por aplicación, antes de iniciar necesitamos agregar un usuario anónimo, esté no tiene autorización para realizar ninguna operación.

@Configuration
@ComponentScan
@ImportResource("classpath:security.xml")
public class MainApp extends Application {
    
    /.../

    /***
     * Iniciar seguridad MODE_GLOBAL establece un unico contexto de seguridad.
     * usemos MODE_GLOBAL solo en apliaciones no web.
     */
    public static void initSecurity() {
        SecurityContextHolder.setStrategyName("MODE_GLOBAL");
        initAnonymous();
    }

    /***
     * Agregar un usuario anonimo
     */
    public static void initAnonymous() {
        AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(
                "anonymous", "anonymous",
                AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));

        SecurityContextHolder.getContext().setAuthentication(auth);
    }

    /***
     * cerrar la session de usuario
     */
    public static void logout(){
        SecurityContextHolder.clearContext();
        initAnonymous();
    }
}

Lo siguiente será definir que métodos estarán protegidos por Spring Security, creamos la interfaz OperationService la misma define un grupo de operaciones matemáticas que ejecutara la aplicación que estamos desarrollando, usaremos las anotaciones @Secured("ROLE_ADMIN") para definir un método protegido que solo puede ser accedido por un usuario con la autoridad: ROLE_ADMIN, del mismo modo usamos @PreAuthorize("hasAnyRole('ROLE_USER', 'ROLE_STANDAR')") para indicar que el método puede ser accedido solo un usuario que tenga una de estas dos autoridades: ROLE_USER o ROLE_STANDAR, los métodos no anotados no estarán protegidos.

public interface OperationService {

    @Secured("ROLE_ADMIN")
    double sumar(double a, double b);

    @PreAuthorize("hasAnyRole('ROLE_USER', 'ROLE_STANDAR')")
    double multiplicar(double a, double b);

    double dividir(double a, double b);
}

Esta es la GUI de la aplicación JavaFX protegida por Spring Security, en la parte superior vemos una pequeña interfaz de login y logout, en la parte inferior se encuentra la implementación de la interfaz OperationService para poder ejecutar debemos hacer login con el usuario requerido por cada operación, recordemos que los usuarios válidos y sus roles están definidos en security.xml.

spring-security javafx

Más adelante veremos cómo almacenar los usuarios en una base de datos, uso de algoritmos hash para la protección de las contraseñas.

GitHub: Integrar Spring Security a JavaFX

Comentarios

Temas relacionados

Entradas populares de este blog

tkinter Grid

tkinter Canvas

Histogramas OpenCV Python

Python Binance API