OAUTH2 - RESOURCE SERVER

CREACIÓN DEL PROYECTO


PROCEDIMIENTOS ALMACENADOS (ORACLE)

CREATE OR REPLACE PACKAGE PCK_PPSEG_SEGURIDAD AS

    PROCEDURE SP_PPSEG_LISTAR_USUARIO (
        O_RESULT     OUT   SYS_REFCURSOR,
        O_CODIGO    OUT   NUMBER,
        O_MENSAJE   OUT   VARCHAR2
    );

END PCK_PPSEG_SEGURIDAD;
/     
CREATE OR REPLACE PACKAGE BODY PCK_PPSEG_SEGURIDAD AS

    PROCEDURE SP_PPSEG_LISTAR_USUARIO (
        O_RESULT     OUT   SYS_REFCURSOR,
        O_CODIGO    OUT   NUMBER,
        O_MENSAJE   OUT   VARCHAR2
    ) AS
    BEGIN
        OPEN O_RESULT FOR
            SELECT
                    U.ID,
                    U.NOMBRE,
                    U.APE_PATERNO,
                    U.APE_MATERNO,
                    U.USERNAME,
                    U.PASSWORD,
                    U.EMAIL,
                    U.TELEFONO
                    FROM PPSEG.USUARIO U;

        O_CODIGO := SQLCODE;
        O_MENSAJE := SQLERRM;
    EXCEPTION
        WHEN OTHERS THEN
            O_CODIGO := SQLCODE;
            O_MENSAJE := SQLERRM;
    END SP_PPSEG_LISTAR_USUARIO;

END PCK_PPSEG_SEGURIDAD;

CONFIGURACION DE DEPENDENCIAS
Achivo pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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>
       <artifactId>panaderia-seg-backend</artifactId>
       <packaging>war</packaging>
       <name>panaderia-seg-backend</name>
       <description>Panaderia seguridad - backend </description>

       <parent>
             <groupId>com.besoft</groupId>
             <artifactId>panaderia-app</artifactId>
             <version>1.0</version>
       </parent>

       <properties>
             <start-class>com.besoft.panaderia.PanaderiaSegBackendApplication</start-class>
             <java.version>1.8</java.version>
       </properties>

       <dependencies>
             <!-- springframework.boot global config -->
             <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter</artifactId>
             </dependency>
             <!-- springframework.boot dependencies -->
             <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-data-jpa</artifactId>
             </dependency>
             <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
             </dependency>
             <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-test</artifactId>
                    <scope>test</scope>
                    <exclusions>
                           <exclusion>
                                  <groupId>org.junit.vintage</groupId>
                                  <artifactId>junit-vintage-engine</artifactId>
                           </exclusion>
                    </exclusions>
             </dependency>
             <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-security</artifactId>
             </dependency>
             <!-- Dependencias Spring Security -->
             <dependency>
                    <groupId>org.springframework.security.oauth</groupId>
                    <artifactId>spring-security-oauth2</artifactId>
                    <version>2.3.4.RELEASE</version>
             </dependency>
             <dependency>
                    <groupId>org.springframework.security</groupId>
                    <artifactId>spring-security-jwt</artifactId>
                    <version>1.1.0.RELEASE</version>
             </dependency>
             <dependency>
                    <groupId>org.springframework.security.oauth.boot</groupId>
                    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                    <version>2.1.0.RELEASE</version>
             </dependency>
             <!-- Dependencia Oracle -->
             <dependency>
                    <groupId>com.oracle</groupId>
                    <artifactId>ojdbc6</artifactId>
                    <version>11.2.0.3</version>
             </dependency>
             <!-- the implementation will be provided by Wildfly / JBoss -->
             <dependency>
                    <groupId>javax.servlet</groupId>
                    <artifactId>javax.servlet-api</artifactId>
                    <scope>provided</scope>
             </dependency>
       </dependencies>

       <build>
             <finalName>panaderia-seg-backend</finalName>
             <resources>
                    <resource>
                           <directory>src/main/resources</directory>
                           <filtering>true</filtering>
                    </resource>
             </resources>
             <plugins>
                    <plugin>
                           <groupId>org.springframework.boot</groupId>
                           <artifactId>spring-boot-maven-plugin</artifactId>
                           <configuration>
                                  <addResources>true</addResources>
                           </configuration>
                    </plugin>
             </plugins>
       </build>

       <profiles>
             <profile>
                    <id>dev</id>
                    <properties>
                           <spring.profiles.active>dev</spring.profiles.active>
                           <logging.level>INFO</logging.level>
                    </properties>
                    <activation>
                           <activeByDefault>true</activeByDefault>
                    </activation>
                    <dependencies>
                           <dependency>
                                  <groupId>org.springframework.boot</groupId>
                                  <artifactId>spring-boot-starter-web</artifactId>
                           </dependency>
                    </dependencies>
             </profile>
             <profile>
                    <id>qa</id>
                    <properties>
                           <spring.profiles.active>qa</spring.profiles.active>
                           <logging.level>INFO</logging.level>
                    </properties>
                    <dependencies>
                           <dependency>
                                  <groupId>org.springframework.boot</groupId>
                                  <artifactId>spring-boot-starter-web</artifactId>
                                  <exclusions>
                                        <exclusion>
                                               <groupId>org.springframework.boot</groupId>
                                               <artifactId>spring-boot-starter-tomcat</artifactId>
                                        </exclusion>
                                  </exclusions>
                           </dependency>
                    </dependencies>
             </profile>
       </profiles>

</project>

CONFIGURACION DE PROPIEDADES
Archivo application.yml

spring:
  profiles:
    active: '@spring.profiles.active@'
  application:
    name: panaderia-seg-backend
security:
  oauth2:
    resource:
      filter-order: 3
      jwt:
        key-value: -----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA74dddBgzojGAODlMGx0mWXIpusTHcY5n3Y7xrPAVdgNsl9CTiZTpxtPHXmOtV+5Kx58q7P+2PsrFZUoGAr4aFzeGIdnE1A2ZtZTknvY4VEvFkWOQyQfm3nIPCQtv6EZv6AFinQyicr7jjapbgb4JjldN+cABbb3eh6lvJP/twwAlrCiuVKfw36Ms9SP3j6duAoI7AaDFY247UYh7ngoGJFV6xkaRzgiBW9OlUpwETCFiZwYtGvPNngHTEWjV2IL1QyZdv+aKbloi+HsvLYRNrhzRaG/3A19NXBntGtdKLqH5PClj7g1YyTaQVyujVREU8zWzXcmmnzJ29RshDRrsXQIDAQAB-----END PUBLIC KEY-----
---
server:
  port: 8080
  servlet:
    context-path: /panaderia-seg-backend
spring:
  profiles: dev
  datasource:
    driverClassName: oracle.jdbc.driver.OracleDriver
    url: "jdbc:oracle:thin:@localhost:1521:orcl"
    password: "1234"
    username: "ppseg"
    testOnBorrow: true
    testWhileIdle: true
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 30000
    validationQuery: SELECT 1 FROM DUAL
    max-active: 15
    max-idle: 10
    max-wait: 8000
    hikari:
      maximum-pool-size: 5
      connection-timeout: 60000
---
spring:
  profiles: qa
  datasource:
    jndi-name: java:/ppsegNoXADS
    testOnBorrow: true
    testWhileIdle: true
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 30000
    validationQuery: SELECT 1 FROM DUAL
    max-active: 15
    max-idle: 10
    max-wait: 8000

HABILITAR EL SERVIDOR DE RECURSOS (RESOURCE SERVER)
Clase PanaderiaSegBackendApplication

package com.besoft.panaderia;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;

@SpringBootApplication
@EnableResourceServer
public class PanaderiaSegBackendApplication {

       private static final Logger log = LoggerFactory.getLogger(PanaderiaSegBackendApplication.class);

       public static void main(String[] args) {
             log.info("---------Start class Application---------");
             SpringApplication.run(PanaderiaSegBackendApplication.class, args);
       }
}

Clase ServletInitializer

package com.besoft.panaderia;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

       @Override
       protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
             return application.sources(PanaderiaSegBackendApplication.class);
       }

}

DEFINIR LAS CLASES REQUEST
Clase UsuarioRequest
package com.besoft.panaderia.dto.request;

import java.io.Serializable;

public class UsuarioRequest implements Serializable {
      
       private static final long serialVersionUID = 1L;
       private Long id;
       private String nombre;
       private String apePaterno;
       private String apeMaterno;
       private String username;
       private String password;
       private String email;
       private String telefono;
       private RolRequest rol;

       public Long getId() {
             return id;
       }

       public void setId(Long id) {
             this.id = id;
       }

       public String getNombre() {
             return nombre;
       }

       public void setNombre(String nombre) {
             this.nombre = nombre;
       }

       public String getApePaterno() {
             return apePaterno;
       }

       public void setApePaterno(String apePaterno) {
             this.apePaterno = apePaterno;
       }

       public String getApeMaterno() {
             return apeMaterno;
       }

       public void setApeMaterno(String apeMaterno) {
             this.apeMaterno = apeMaterno;
       }

       public String getUsername() {
             return username;
       }

       public void setUsername(String username) {
             this.username = username;
       }

       public String getPassword() {
             return password;
       }

       public void setPassword(String password) {
             this.password = password;
       }

       public String getEmail() {
             return email;
       }

       public void setEmail(String email) {
             this.email = email;
       }

       public String getTelefono() {
             return telefono;
       }

       public void setTelefono(String telefono) {
             this.telefono = telefono;
       }

       public RolRequest getRol() {
             return rol;
       }

       public void setRol(RolRequest rol) {
             this.rol = rol;
       }
}


Clase RolRequest
package com.besoft.panaderia.dto.request;

import java.io.Serializable;

public class RolRequest implements Serializable {
      
       private static final long serialVersionUID = 1L;
       private Long id;
       private String nombre;

       public Long getId() {
             return id;
       }

       public void setId(Long id) {
             this.id = id;
       }

       public String getNombre() {
             return nombre;
       }

       public void setNombre(String nombre) {
             this.nombre = nombre;
       }
}


DEFINIR LAS CLASES RESPONSE
Clase UsuarioResponse
package com.besoft.panaderia.dto.response;

import java.io.Serializable;

public class UsuarioResponse implements Serializable {

       private static final long serialVersionUID = 1L;
       private Long id;
       private String nombre;
       private String apePaterno;
       private String apeMaterno;
       private String username;
       private String password;
       private String email;
       private String telefono;
       private RolResponse rol;

       public Long getId() {
             return id;
       }

       public void setId(Long id) {
             this.id = id;
       }

       public String getNombre() {
             return nombre;
       }

       public void setNombre(String nombre) {
             this.nombre = nombre;
       }

       public String getApePaterno() {
             return apePaterno;
       }

       public void setApePaterno(String apePaterno) {
             this.apePaterno = apePaterno;
       }

       public String getApeMaterno() {
             return apeMaterno;
       }

       public void setApeMaterno(String apeMaterno) {
             this.apeMaterno = apeMaterno;
       }

       public String getUsername() {
             return username;
       }

       public void setUsername(String username) {
             this.username = username;
       }

       public String getPassword() {
             return password;
       }

       public void setPassword(String password) {
             this.password = password;
       }

       public String getEmail() {
             return email;
       }

       public void setEmail(String email) {
             this.email = email;
       }

       public String getTelefono() {
             return telefono;
       }

       public void setTelefono(String telefono) {
             this.telefono = telefono;
       }

       public RolResponse getRol() {
             return rol;
       }

       public void setRol(RolResponse rol) {
             this.rol = rol;
       }
}


Clase RolResponse
package com.besoft.panaderia.dto.response;

import java.io.Serializable;

public class RolResponse implements Serializable {

       private static final long serialVersionUID = 1L;
       private Long id;
       private String nombre;

       public Long getId() {
             return id;
       }

       public void setId(Long id) {
             this.id = id;
       }

       public String getNombre() {
             return nombre;
       }

       public void setNombre(String nombre) {
             this.nombre = nombre;
       }
}

Clase OutReponse
package com.besoft.panaderia.dto.response;

public class OutResponse<T> {
       private Integer oCodigo;
       private String oMensaje;
       private T oResult;

       public Integer getoCodigo() {
             return oCodigo;
       }

       public void setoCodigo(Integer oCodigo) {
             this.oCodigo = oCodigo;
       }

       public String getoMensaje() {
             return oMensaje;
       }

       public void setoMensaje(String oMensaje) {
             this.oMensaje = oMensaje;
       }

       public T getoResult() {
             return oResult;
       }

       public void setoResult(T oResult) {
             this.oResult = oResult;
       }
}

CLASES DE ACCESO A DATOS (DAO)
Interface UsuarioDao
package com.besoft.panaderia.dao;

import com.besoft.panaderia.dto.request.UsuarioRequest;
import com.besoft.panaderia.dto.response.OutResponse;
import com.besoft.panaderia.dto.response.UsuarioResponse;

public interface UsuarioDao {

       public OutResponse<UsuarioResponse> registrarUsuario(UsuarioRequest req);
}

Clase UsuarioDaoImpl
package com.besoft.panaderia.dao.impl;

import java.sql.Types;
import java.util.Map;

import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;
import com.besoft.panaderia.dao.UsuarioDao;
import com.besoft.panaderia.dto.request.UsuarioRequest;
import com.besoft.panaderia.dto.response.OutResponse;
import com.besoft.panaderia.dto.response.RolResponse;
import com.besoft.panaderia.dto.response.UsuarioResponse;

@Repository
public class UsuarioDaoImpl implements UsuarioDao {

       Logger log = LoggerFactory.getLogger(UsuarioDaoImpl.class);

       @Autowired
       DataSource dataSource;

       private PasswordEncoder encoder = new BCryptPasswordEncoder();

       @Override
       public OutResponse<UsuarioResponse> registrarUsuario(UsuarioRequest req) {
             OutResponse<UsuarioResponse> res = new OutResponse<>();

             Integer oCodigo = -1;
             String oMensaje = "";
             try {
                    SimpleJdbcCall jdbcCall = new SimpleJdbcCall(dataSource).withSchemaName("PPSEG")
                                  .withCatalogName("PCK_PPSEG_SEGURIDAD").withProcedureName("SP_PPSEG_REGISTRAR_USUARIO");

                    MapSqlParameterSource in = new MapSqlParameterSource();
                    in.addValue("I_NOMBRE", req.getNombre(), Types.NUMERIC);
                    in.addValue("I_APE_PATERNO", req.getApePaterno(), Types.VARCHAR);
                    in.addValue("I_APE_MATERNO", req.getApeMaterno(), Types.VARCHAR);
                    in.addValue("I_EMAIL", req.getEmail(), Types.VARCHAR);
                    in.addValue("I_TELEFONO", req.getTelefono(), Types.VARCHAR);
                    in.addValue("I_USERNAME", req.getUsername(), Types.VARCHAR);
                    in.addValue("I_PASSWORD", encoder.encode(req.getPassword()), Types.VARCHAR);
                    in.addValue("I_ID_ROL", req.getRol().getId(), Types.NUMERIC);

                    Map<String, Object> out = jdbcCall.execute(in);

                    oCodigo = Integer.parseInt(out.get("O_CODIGO").toString());
                    oMensaje = out.get("O_MENSAJE").toString();

                    if (oCodigo == 0) {// CONSULTA CORRECTA
                           Long id = Long.parseLong(out.get("O_ID").toString());

                           UsuarioResponse usuarioResp = new UsuarioResponse();
                           usuarioResp.setId(id);
                           usuarioResp.setNombre(req.getNombre());
                           usuarioResp.setApePaterno(req.getApePaterno());
                           usuarioResp.setApeMaterno(req.getApeMaterno());
                           usuarioResp.setEmail(req.getEmail());
                           usuarioResp.setTelefono(req.getTelefono());
                           usuarioResp.setUsername(req.getUsername());
                           usuarioResp.setPassword(req.getPassword());

                           RolResponse rol = new RolResponse();
                           rol.setId(req.getRol().getId());
                           rol.setNombre(req.getRol().getNombre());

                           res.setoCodigo(oCodigo);
                           res.setoMensaje(oMensaje);
                           res.setoResult(usuarioResp);
                    } else {
                           res.setoCodigo(oCodigo);
                           res.setoMensaje(oMensaje);
                           res.setoResult(null);
                    }
             } catch (Exception e) {
                    res.setoCodigo(500);
                    res.setoMensaje(e.getMessage());
                    res.setoResult(null);
                    log.info("[AUTENTICACION][DAO][EXCEPCION][" + e.getMessage() + "]");
             }
             return res;
       }
}

CLASES DE LOGICA DEL NEGOCIO (SERVICE)
Interface UsuarioService
package com.besoft.panaderia.service;

import com.besoft.panaderia.dto.request.UsuarioRequest;
import com.besoft.panaderia.dto.response.OutResponse;
import com.besoft.panaderia.dto.response.UsuarioResponse;

public interface UsuarioService {

       public OutResponse<UsuarioResponse> registrarUsuario(UsuarioRequest req);
}

Clase UsuarioServiceImpl
package com.besoft.panaderia.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.besoft.panaderia.dao.UsuarioDao;
import com.besoft.panaderia.dto.request.UsuarioRequest;
import com.besoft.panaderia.dto.response.OutResponse;
import com.besoft.panaderia.dto.response.UsuarioResponse;
import com.besoft.panaderia.service.UsuarioService;

@Service
public class UsuarioServiceImpl implements UsuarioService {

       @Autowired
       UsuarioDao usuarioDao;

       @Override
       public OutResponse<UsuarioResponse> registrarUsuario(UsuarioRequest req) {
             return usuarioDao.registrarUsuario(req);
       }
}

CREAR LA CLASE DE CONFIGURACION DE SEGURIDAD
Clase SecurityConfig
package com.besoft.panaderia.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.security.config.http.SessionCreationPolicy;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

       @Override
       protected void configure(HttpSecurity http) throws Exception {
             http.authorizeRequests()
             .anyRequest()
             .authenticated()
             .and().sessionManagement()
             .sessionCreationPolicy(SessionCreationPolicy.NEVER);
       }
}


CREAR EL MODELO DE MAPEO DEL ACCES TOKEN
Clase TokenMapper
package com.besoft.panaderia.dto;

import java.util.ArrayList;
import java.util.List;

public class TokenMapper {
       private Long id;
       private String nombre;
       private String apePaterno;
       private String apeMaterno;
       private String email;
       private String telefono;
       private Long idRol;
       private String nombreRol;
       private List<String> grantedAuthoritiesList = new ArrayList<>();

       public Long getId() {
             return id;
       }

       public void setId(Long id) {
             this.id = id;
       }

       public String getNombre() {
             return nombre;
       }

       public void setNombre(String nombre) {
             this.nombre = nombre;
       }

       public String getApePaterno() {
             return apePaterno;
       }

       public void setApePaterno(String apePaterno) {
             this.apePaterno = apePaterno;
       }

       public String getApeMaterno() {
             return apeMaterno;
       }

       public void setApeMaterno(String apeMaterno) {
             this.apeMaterno = apeMaterno;
       }

       public String getEmail() {
             return email;
       }

       public void setEmail(String email) {
             this.email = email;
       }

       public String getTelefono() {
             return telefono;
       }

       public void setTelefono(String telefono) {
             this.telefono = telefono;
       }

       public Long getIdRol() {
             return idRol;
       }

       public void setIdRol(Long idRol) {
             this.idRol = idRol;
       }

       public String getNombreRol() {
             return nombreRol;
       }

       public void setNombreRol(String nombreRol) {
             this.nombreRol = nombreRol;
       }

       public List<String> getGrantedAuthoritiesList() {
             return grantedAuthoritiesList;
       }

       public void setGrantedAuthoritiesList(List<String> grantedAuthoritiesList) {
             this.grantedAuthoritiesList = grantedAuthoritiesList;
       }
}


Clase JwtConverter

package com.besoft.panaderia.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.boot.autoconfigure.security.oauth2.resource.JwtAccessTokenConverterConfigurer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.stereotype.Component;

import com.besoft.panaderia.dto.TokenMapper;

@Component
public class JwtConverter extends DefaultAccessTokenConverter implements JwtAccessTokenConverterConfigurer {

       @Override
       public void configure(JwtAccessTokenConverter converter) {
             converter.setAccessTokenConverter(this);
       }

       @Override
       public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
             OAuth2Authentication auth = super.extractAuthentication(map);
             TokenMapper details = new TokenMapper();
             if (map.get("id") != null)
                    details.setId(Long.parseLong(map.get("id").toString()));
             if (map.get("nombre") != null)
                    details.setNombre(map.get("nombre").toString());
             if (map.get("apePaterno") != null)
                    details.setApePaterno(map.get("apePaterno").toString());
             if (map.get("apeMaterno") != null)
                    details.setApeMaterno(map.get("apeMaterno").toString());
             if (map.get("email") != null)
                    details.setEmail(map.get("email").toString());
             if (map.get("telefono") != null)
                    details.setTelefono(map.get("telefono").toString());
             if (map.get("idRol") != null)
                    details.setIdRol(Long.parseLong(map.get("idRol").toString()));
             if (map.get("nombreRol") != null)
                    details.setNombreRol(map.get("nombreRol").toString());
             if (auth.getAuthorities() != null && !auth.getAuthorities().isEmpty()) {
                    List<String> authorities = new ArrayList<>();
                    for (GrantedAuthority gn : auth.getAuthorities()) {
                           authorities.add(gn.getAuthority());
                    }
             }
             auth.setDetails(details);
             return auth;
       }

}

Clase CorsFilter
La clase CORS permite configurar los permisos de acceso de un determinado “host”, en caso no ponerlo te lanza el siguiente error:
“Response for prelight does not have http ok status, no Access control Allow header is presenton requested resource”.

package com.besoft.panaderia.config;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {

       @Override
       public void init(FilterConfig filterConfig) {
       }

       @Override
       public void destroy() {

       }

       @Override
       public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
                    throws IOException, ServletException {
             HttpServletRequest request = (HttpServletRequest) req;
             HttpServletResponse response = (HttpServletResponse) res;

             response.setHeader("Access-Control-Allow-Origin", "*");
             response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
             response.setHeader("Access-Control-Max-Age", "3600");
             response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, content-type");

             if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
                    response.setStatus(HttpServletResponse.SC_OK);
             } else {
                    chain.doFilter(req, res);
             }
       }

}


CREAMOS LOS CONTROLADORES
Clase UsuarioController
package com.besoft.panaderia.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.besoft.panaderia.dto.TokenMapper;
import com.besoft.panaderia.dto.request.UsuarioRequest;
import com.besoft.panaderia.dto.response.OutResponse;
import com.besoft.panaderia.dto.response.UsuarioResponse;
import com.besoft.panaderia.service.UsuarioService;

@RestController
@RequestMapping("/usuario")
public class UsuarioController {

       @Autowired
       UsuarioService usuarioService;

       @PreAuthorize("hasAnyRole('ADMIN','VENTAS')")
       @PostMapping(value = "/registrar-usuario")
       public OutResponse<UsuarioResponse> registrarUsuario(@RequestBody UsuarioRequest req) {
             TokenMapper tokenMapper = (TokenMapper) ((OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails()).getDecodedDetails();

             System.out.println("Token nombre: " + tokenMapper.getNombre());

             return usuarioService.registrarUsuario(req);
       }

}

Consulta POSTMAN
Header




Body



Resultado
{
    "oCodigo"0,
    "oMensaje""ORA-0000: normal, successful completion",
    "oResult": {
        "id"24,
        "nombre""COCO",
        "apePaterno""PEREZ",
        "apeMaterno""PEREZ",
        "username""coca",
        "password""1234",
        "email""coco@gmail.com",
        "telefono""929181945",
        "rol"null
    }
}

Consultar API de recursos por JQuery