...
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 oauth app.author=acade app.apiname=expedienteacademico-api app.server.path=/${app.author}/${app.apiname} ############## Entorno app.env=desa ########## BASE DE DATOS ########## spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect spring.jpa.generate-ddl=false spring.jpa.hibernate.ddl-auto = validate spring.datasource.url=jdbc:oracle:thin:@hydra-prescan.atica.um.es:1526/ZEUSDESA spring.datasource.username=USER spring.datasource.password=PASSWORD ########## ACTUATOR ########## management.endpoints.enabled-by-default=false management.endpoint.health.enabled=true management.endpoints.web.exposure.include=health management.health.probes.enabled=true management.endpoint.health.group.liveness.include=livenessstate,ping management.endpoint.health.group.readiness.include=readinessstate,ping management.endpoint.health.group.custom.include=db ########## 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#### Accesslog # here we say that we want to enable accesslog server.tomcat.accesslog.enabled=true # it is important to understand what the options means: # 'directory/prefix + suffix + file-date-format' will be # the file that tomcat will try to open. # /dev/stdout is standard output, so we want tomcat # to write to that fd. Then, we need to play with # directory, prefix, suffix and file-date-format to match our desired path. server.tomcat.accesslog.directory=/dev server.tomcat.accesslog.prefix=stdout server.tomcat.accesslog.buffered=false # Don't use empty double quotes, see below server.tomcat.accesslog.suffix= server.tomcat.accesslog.file-date-format= server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" "%{X-Forwarded-For}i" %D "%{UMU-Request-UUID}o" #### Actuator management.endpoints.enabled-by-default=false management.endpoint.health.enabled=true management.health.ping.enabled=true management.endpoint.health.group.liveness.include=livenessstate,ping management.endpoint.health.group.readiness.include=readinessstate,ping,db management.endpoint.health.group.check.include=readinessstate,dependencies,db management.endpoint.health.group.check.show-details=always #### Logs # 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 # FundeWebJS Habilitar filtro para loggear request/response fdwjs.api.logging.enable=true fdwjs.api.logging.client.enable=true fdwjs.api.logging.query.enable=true fdwjs.api.logging.headers.enable=true fdwjs.api.logging.payload.enable=true fdwjs.api.logging.payload.maxLength=6400 fdwjs.api.logging.url-patterns=* # FundeWebJS Habilitar endpoint jsn.logger fdwjs.api.frontLogger.enable=true #### SSO URL cas.url=https://entrada.test.um.es client.id=basicbackend server.scopes=SCOPE_micampus #### SpringDoc OpenAPI Documentation springdoc.api-docs.path=/api-docs # Propiedades inventadas para reubicar las peticiones springdoc.server.url=https://apidesa.um.es springdoc.server.path=/${app.author}/${app.apiname} springdoc.security.issuer-uri=${cas.url}/cas/oidc #### Spring Security Resource Server spring.security.oauth2.resourceserver.jwt.jws-algorithm=RS512 spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${cas.url}/cas/oidc/jwks #spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=${cas.url}/cas/oidc/introspect #spring.security.oauth2.resourceserver.opaquetoken.client-id=plain_user #spring.security.oauth2.resourceserver.opaquetoken.client-secret=${client.secret} #### Base de datos spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect spring.jpa.generate-ddl=false spring.jpa.hibernate.ddl-auto = validate spring.datasource.url=jdbc:oracle:thin:@hydra-prescan.atica.um.es:1526/ZEUSDESA spring.datasource.username=USER spring.datasource.password=PASSWORD |
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í.
...
| 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 ( basePackagesscanBasePackages = { "es.um.atica.pruebaspose[PAQUETE_APPLICATION]", "es.um.atica.fundewebjs" } ) public class PruebasPoseApplication { public static void main(String[] args) { SpringApplication.run(PruebasPoseApplication.class, args); } } |
WebSecurity
Configuración CORS
En el paquete es.um.atica.[APLICACION].config añadiremos una clase CorsConfig, que contendrá lo siguientePor 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[APLICACION].config; import java.util.Arrays; import org.springframework.context.annotation.Bean; import org.springframework.security.configcontext.annotation.web.builders.HttpSecurityConfiguration; 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; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapterCorsConfig { // Filtro CORS @Bean CorsConfigurationSource @Override protected void configure(HttpSecurity http) throws Exception { // CORS y HTTPS obligatorio: // http.cors().and().csrf().disable().and().requiresChannel().anyRequest().requiresSecure(); // Solo CORS: corsConfigurationSource() { final CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOriginPatterns( Arrays.asList( "*" ) ); configuration.setAllowedMethods( Arrays.asList( "*" ) ); configuration.setAllowedHeaders( Arrays.asList( "*" ) ); configuration.setAllowCredentials( true ); final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration( "/**", configuration ); return source; } } |
¡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 | ||
|---|---|---|
| ||
httpconfiguration.corssetAllowedOriginPatterns().and().csrf().disable(); Arrays.asList( "*" ) ); |
Utilizábamos:
| Bloque de código | ||
|---|---|---|
| ||
} // Filtro CORS @Bean 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 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.
...
: 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.
Configuración de seguridad
Por otro lado, nos haremos una clase java para especificar la configuración de seguridad web, que estará también en es.um.atica.[APLICACION].config, y que se llamará SecurityConfig. Contendrá lo siguiente:
| Bloque de código | ||
|---|---|---|
| ||
package es.um.atica.[APLICACION].config; import org.springframework.beans.factory.annotation.Value; import 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. |
...
org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value( "${server.scopes}" )
private String[] serverScopes;
@Value( "${app.server.path}" )
private String apiPath;
/**
* Proveedor de gestion de acceoss
*/
@Override
protected void configure( HttpSecurity http ) throws Exception {
http.requestMatchers().antMatchers( "/public/**" ).and().requestMatchers().antMatchers( apiPath + "/**" ).and()
.sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS )
// configuro politica de sesion sin estado
.and().cors() // Aniado configuracion CORS por defecto
.and().csrf().disable().authorizeRequests().mvcMatchers( apiPath + "/public/**" ).permitAll()
.mvcMatchers( apiPath + "/**" ).hasAnyAuthority( serverScopes ).anyRequest().authenticated().and()
.oauth2ResourceServer().jwt();
}
} |
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.
...