| Tabla de contenidos |
|---|
Explicación en vídeo
...
| Videolink | ||||
|---|---|---|---|---|
|
pom.xml
Tendremos que añadir las siguientes dependencias en el El fichero pom.xml , entre </properties> y </project>
| Bloque de código | ||
|---|---|---|
| ||
<dependencies>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.4.12.Final</version>
<scope>provided</scope>
</dependency>
<!-- Real DB -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>jdbc.driver</artifactId>
<version>11.2.0.3.0</version>
</dependency>
<!-- UNDERTOW -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starte-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- SECURITY -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- TEST -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starte-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Test DB -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<!-- Selenium -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<!-- <version>3.141.59</version> -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- Log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-layout-template-json</artifactId>
<version>2.14.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- frontLogger -->
<dependency>
<groupId>es.um.atica.fundewebjs.fundewebjs-api</groupId>
<artifactId>fundewebjs-lagar</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<repositories>
<repository>
<id>archiva.atica.umu.es</id>
<name>ATICA - UMU Repository</name>
<url>https://archiva.um.es/archiva/repository/FundeWeb/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>fundewebjs.archiva.atica.umu.es</id>
<name>ATICA - UMU Repository - FundeWebJS</name>
<url>https://archiva.um.es/archiva/repository/FundeWebJS/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository> </repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>${hibernate.version}</version>
<executions>
<execution>
<configuration>
<failOnError>true</failOnError>
<enableLazyInitialization>true</enableLazyInitialization>
<enableDirtyTracking>true</enableDirtyTracking>
<enableAssociationManagement>true</enableAssociationManagement>
<enableExtendedEnhancement>false</enableExtendedEnhancement>
</configuration>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- JaCoCo configuration -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Enunciate -->
<plugin>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-maven-plugin</artifactId>
<version>2.13.0</version>
<dependencies>
<dependency>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-lombok</artifactId>
<version>2.9.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>fdwjs</id>
<configuration>
<docsDir>${basedir}/src/main/resources/</docsDir>
<docsSubdir>static/docs/</docsSubdir>
</configuration>
</execution>
</executions>
</plugin>
<!-- FIN Enunciate -->
</plugins>
</build> |
application.properties
Como hemos visto en el apartado anterior, en el archivo application.properties incluiremos algunas variables de configuración del proyecto:
| Bloque de código |
|---|
########## RUTA BASE REST ##########
server.servlet.context-path=/api
########## BASE DE DATOS ##########
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.Oracle10gDialect
spring.jpa.hibernate.ddl-auto = validate
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@hydra-prescan.atica.um.es:1526/ZEUSDESA
spring.datasource.username=USER
spring.datasource.password=PASSWORD
########## FRONT-LOGGER ##########
# FundeWebJS Habilitar endpoint jsn.logger
fdwjs.api.frontLogger.enable=true
# FundeWebJS Habilitar filtro para cabeceras en logs MDC de lagar
fdwjs.api.lagar.enable=true
fdwjs.api.lagar.headers=UMU-User-UUID,UMU-Client-APP |
Si queremos cambiar el puerto que utiliza nuestra aplicación, que por defecto es el 8080, podemos hacerlo con la propiedad server.port. Otras propiedades que haya que definirse para otras funcionalidades, como para el login, se incluyen en su página de documentación correspondiente. Si queremos ver las propiedades de configuración que ofrece Spring podemos consultarlas aquí.
log4j2.xml
Debemos crear el fichero log4j2.xml en la carpeta /src/main/resources con el siguiente contenido:
| Bloque de código | ||
|---|---|---|
| ||
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorinterval="60" >
<Properties>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">dd-MM-yyyy HH:mm:ss.SSS</Property>
<Property name="CONSOLE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties>
<Appenders>
<Console name="local" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
</Console>
<Console name="json" target="SYSTEM_OUT" follow="true">
<JsonTemplateLayout eventTemplateUri="classpath:LogstashJsonEventLayoutV1.json" locationInfoEnabled="true" stackTraceEnabled="true"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
<Root level="debug">
<AppenderRef ref="local" />
</Root>
</Loggers>
</Configuration> |
Este es un archivo de configuración para los logs, que vienen explicados más detalladamente en esta página.
Clase inicial de la aplicación
En la clase que inicia la aplicación, que será algo como NombreApplication.java, sustituyendo Nombre por el de nuestra aplicación, tendremos que añadir a la clase la anotación @ComponentScan, con el contenido siguiente:
| Bloque de código | ||
|---|---|---|
| ||
@ComponentScan( basePackages = {
"es.um.atica.aplicacion", "es.um.atica.fundewebjs"
} ) |
Ahí, tenemos que cambiar aplicación por el paquete base de nuestra aplicación.
Con esto, un ejemplo de esta clase inicial podría ser el siguiente:
| Bloque de código | ||
|---|---|---|
| ||
package es.um.atica.pruebaspose;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan( basePackages = {
"es.um.atica.pruebaspose", "es.um.atica.fundewebjs"
} )
public class PruebasPoseApplication {
public static void main(String[] args) {
SpringApplication.run(PruebasPoseApplication.class, args);
}
} |
WebSecurity
Por otro lado, nos haremos una clase java para especificar la configuración de seguridad web, que debe extender a WebSecurityConfigurerAdapter e incluir la anotación @EnableWebSecurity:
| Bloque de código | ||
|---|---|---|
| ||
package es.um.atica.helloworld.config;
import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// CORS y HTTPS obligatorio:
// http.cors().and().csrf().disable().and().requiresChannel().anyRequest().requiresSecure();
// Solo CORS:
http.cors().and().csrf().disable();
}
// Filtro CORS
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
} |
Esta configuración tendrá que ser ampliada si se incluye el login con el CAS, pero esa configuración se indicará en la página correspondiente. También hay que ver si en local y en otros entornos tenemos que poner configuración diferente (https obligatorio, por ejemplo). En este caso podemos definirnos una variable en application.properties que indique el entorno en el que estás, y comprobarlo con un if. Por ejemplo, si estás en local, la configuración sin https, si no, con https.
¡Ojo! En versiones anteriores de Spring Boot (anteriores a la 2.4.0), en el filtro del CORS, en vez de:
| Bloque de código | ||
|---|---|---|
| ||
configuration.setAllowedOriginPatterns( Arrays.asList( "*" ) ); |
Utilizábamos:
| Bloque de código | ||
|---|---|---|
| ||
configuration.setAllowedOrigins(Arrays.asList("*")); |
Pero tras los cambios, con setAllowedOrigins nos salta el siguiente error:
| Bloque de código |
|---|
2021-01-08 10:21:50.656 ERROR 10568 --- [ XNIO-1 task-1] io.undertow.request : UT005023: Exception handling request to /loquesea
java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*"since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead. |
Así que en función de la versión, podemos encontrarnos algún error, por lo que debemos tener esto en cuenta.
Con esta configuración ya podemos tener nuestra aplicación funcionando sin problemas, pero si por algún motivo queremos poner https para hacer pruebas en local, en nuestro equipo, podemos generarnos un certificado autofirmado.
Generar certificado autofirmado
...
se genera automáticamente al crear el proyecto (Creación y estructura de proyecto SpringBoot).
| Info |
|---|
Con la configuración estándar no es necesario realizar ninguna modificación en el fichero pom.xml. |
A continuación se detallan aspectos relevantes de la configuración:
- Todas las APIs deben heredar del parent fundewebjs-api-parent.
Este parent fija las versiones y plugins a utilizar en las APIs. - Todas las APIs deben tener la dependencia fundewebjs-spring-boot-starter.
Esta dependencia importa el resto de librerías necesarias para trabajar con proyectos estándar.
Además, esta librería incluye funcionalidades comunes.
Ver la perspectiva Dependency Hierarchy del fichero pom.xml para localizar las librerías importadas. Disponible aquí Migración de APIs a Parent FundeWebJS#1.Ficheropom.xml. Todas las APIs deben incluir la dependencia bom de spring-boot-dependencies en la etiqueta <dependencyManagement>
Bloque de código <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>OPCIONAL. Si fuera necesario añadir alguna dependencia de Spring-cloud que fundewebjs-spring-boot-starter no importa, SOLO SI NO LA IMPORTA, habrá que configurar la dependencia bom de Spring-cloud en <dependencyManagement> (junto a spring-boot-dependencies):
Bloque de código <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>Si se utiliza alguna dependencia opcional de fundewebjs, y no se ha añadido al generar el proyecto, vaya a la página de confluence de la librería correspondiente para ver cómo configurarla => Librerías Backend FundeWebJS.
...
application.properties
| Advertencia |
|---|
Dentro del fichero de application.properties NO se permiten caracteres especiales, ni en el fichero ni en los comentarios, como acentos, Ñ, etc. Esto causará que el proyecto no compile en local dando a un error |
El fichero application.properties viene preconfigurado con todas las variables por defecto para trabajar en local.
Solo es necesario realizar las siguientes modificaciones sobre el fichero generado en la creación:
| Bloque de código |
|---|
#### Ruta oauth
#app.author=
#app.apiname=
..........
..........
#spring.datasource.url=jdbc:oracle:thin:@hydra-prescan.atica.um.es:1526/ZEUSDESA
#spring.datasource.username=
#spring.datasource.password=
..........
.......... |
Completar y descomentar las variables:
- app.author: será el nombre del grupo. Por ejemplo, "acade".
- app.apiname: el nombre del servicio. Por ejemplo, "resguardomatricula-api".
Estas dos forman la ruta base del servicio. Con estos ejemplos, sería /acade/resguardomatricula-api.
Además:
- spring.datasource.url: Cadena de conexión a BBDD. Por defecto contra ZEUSDESA.
- spring.datasource.username: Usuario de BBDD a utilizar en la aplicación.
- spring.datasource.password: Contraseña del usuario.
...
log4j2.xml
El fichero log4j2.xml se genera automáticamente y no es necesario modificarlo.
Este es un archivo de configuración para los logs, que vienen explicados más detalladamente en Logs en Spring Boot.
...
Clase inicial de la aplicación
En la clase que inicia la aplicación, que será algo como NombreApplication.java, sustituyendo Nombre por el de nuestra aplicación, tendremos que añadir a la notación SpringBootApplication el atributo scanBasePackages, con el contenido siguiente:
| Bloque de código | ||
|---|---|---|
| ||
@SpringBootApplication( scanBasePackages = {
"es.um.atica.[PAQUETE_APPLICATION]", "es.um.atica.fundewebjs"
} ) |
Ahí, tenemos que cambiar aplicación por el paquete base de nuestra aplicación.
Con esto, un ejemplo de esta clase inicial podría ser el siguiente:
| Bloque de código | ||
|---|---|---|
| ||
package es.um.atica.pruebaspose;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication ( scanBasePackages = {
"es.um.atica.[PAQUETE_APPLICATION]", "es.um.atica.fundewebjs"
} )
public class PruebasPoseApplication {
public static void main(String[] args) {
SpringApplication.run(PruebasPoseApplication.class, args);
}
} |
...
Configuración CORS
| Info |
|---|
Esta configuración, a partir de ahora, se realizará con la clase FundeWebJSCorsConfig de la librería fundewebjs-spring-boot-starter. Si se quiere modificar la configuración por defecto, puede mantenerse en el proyecto y poner en el application.properties la propiedad: fdwjs.starter.cors.enable=false. |
...
Configuración de seguridad
| Info |
|---|
La configuración de seguridad estándar se realizará, a partir de ahora, en la clase FundeWebJSSecurityConfig incluida en la librería fundewebjs-spring-boot-starter. |
Si se desea securizar nuestra API con un nivel de seguridad LoA mínimo, diríjase a la página Configuración de seguridad LoA con Oauth.
Próximamente estára disponible una sección nueva en confluence con todas las funcionalidades para securizar endpoints.
...
Utilizar https en local: generar certificado autofirmado
En vez de generar un certificado nuevo, podemos utilizar los que vienen aquí: certs.rar
Contiene keystore.p12, que es el que utilizaremos en el backend, y los dos .pem para el frontend.
| Expandir | ||||
|---|---|---|---|---|
| ||||
Para generar un certificado autofirmado, utilizaremos el comando
Donde:
Tras introducir el comando nos preguntará una serie de datos, que podemos pasar directamente con Enter, dejándolos sin indicar (no son necesarios). Para confirmar, tendremos que escribir “si” (o “yes”, si es que lo tenemos en inglés). Por último, nos preguntará la contraseña para el certificado, que si pulsamos Enter directamente será la misma que hemos puesto en el comando para el keystore:
|
Añadir certificado a nuestra aplicación
En application.properties debemos añadir lo siguiente (cambiando el valor de descomentar las siguientes properties y añadir la ruta al key-store en nuestra máquina en la propiedad server.ssl.key-store por la ruta en nuestra máquina):
| Bloque de código |
|---|
# The format used for the keystore. It could be set to JKS in case it is a JKS file server.ssl.key-store-type=PKCS12 # The path to the keystore containing the certificate server.ssl.key-store=C:/Users/guillermo.castillo/keystore.p12/certs/keystore.p12 # The password used to generate the keystore server.ssl.key-store-password=password # The password used to generate the certificate server.ssl.key-password=password # The passwordalias usedmapped to generate the keystore server.ssl.key-store-password=password # The password used to generate the certificate server.ssl.key-password=password # The alias mapped to the certificate server.ssl.key-alias=tomcatcertificate server.ssl.key-alias=tomcat |
...
Referencias
...
| Contenido por etiqueta | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
| Propiedades de página | ||
|---|---|---|
| ||
|