From 482261845ec352d4b8af011e4d64fc9279449cb2 Mon Sep 17 00:00:00 2001 From: Alberto Trevezani Date: Wed, 1 Nov 2023 11:25:51 -0300 Subject: [PATCH 1/5] =?UTF-8?q?Rotinas=20para=20gerar=20a=20libera=C3=A7?= =?UTF-8?q?=C3=A3o=20da=20utiliza=C3=A7=C3=A3o=20da=20empresa=20no=20siste?= =?UTF-8?q?ma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 9 ++ .../web/utilerias/security/AESGSMHelper.java | 106 +++++++++++++ .../security/SecurityEmpresaToken.java | 140 ++++++++++++++++++ .../security/exception/SecurityException.java | 13 ++ .../tests/SecurityEmpresaTokenTest.java | 91 ++++++++++++ ...aTest.java => SerieEmbarcadaTest.java.old} | 0 6 files changed, 359 insertions(+) create mode 100644 src/java/com/rjconsultores/ventaboletos/web/utilerias/security/AESGSMHelper.java create mode 100644 src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java create mode 100644 src/java/com/rjconsultores/ventaboletos/web/utilerias/security/exception/SecurityException.java create mode 100644 tests/com/rjconsultores/tests/SecurityEmpresaTokenTest.java rename tests/com/rjconsultores/tests/{SerieEmbarcadaTest.java => SerieEmbarcadaTest.java.old} (100%) diff --git a/pom.xml b/pom.xml index f2f0737be..5220d9f91 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,15 @@ + tests + + + tests + + **/*.java + + + maven-compiler-plugin diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/AESGSMHelper.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/AESGSMHelper.java new file mode 100644 index 000000000..bc7f43653 --- /dev/null +++ b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/AESGSMHelper.java @@ -0,0 +1,106 @@ +package com.rjconsultores.ventaboletos.web.utilerias.security; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; + +public class AESGSMHelper { + private final String SECRET_KEY = "RJ@2019#c0n5ul10r35"; + private final String SALT = "HrqoFr44GtkAhhYN+jP8Ag=="; + private final String ENCRYPT_ALGO = "AES/GCM/NoPadding"; + private final int TAG_LENGTH_BIT = 128; + private final int IV_LENGTH_BYTE = 12; + + private final Charset UTF_8 = StandardCharsets.UTF_8; + + public String encrypt(String value) throws Exception { + SecretKey secret = getAESKeyFromPassword(SECRET_KEY.toCharArray()); + + byte[] pText = value.getBytes(StandardCharsets.UTF_8); + byte[] iv = getRandomNonce(12); + byte[] cipherText = encrypt(pText, secret, iv); + + byte[] cipherTextWithIv = ByteBuffer.allocate(iv.length + cipherText.length) + .put(iv) + .put(cipherText) + .array(); + + return hex(cipherTextWithIv); + } + + private byte[] encrypt(byte[] pText, SecretKey secret, byte[] iv) throws Exception { + Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO); + cipher.init(Cipher.ENCRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv)); + + byte[] encryptedText = cipher.doFinal(pText); + + return encryptedText; + + } + + public String decrypt(String value) throws Exception { + SecretKey secret = getAESKeyFromPassword(SECRET_KEY.toCharArray()); + + byte[] cText = unhex(value); + + ByteBuffer bb = ByteBuffer.wrap(cText); + + byte[] iv = new byte[IV_LENGTH_BYTE]; + bb.get(iv); + + byte[] cipherText = new byte[bb.remaining()]; + bb.get(cipherText); + + String plainText = decrypt(cipherText, secret, iv); + + return plainText; + } + + private String decrypt(byte[] cText, SecretKey secret, byte[] iv) throws Exception { + Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO); + cipher.init(Cipher.DECRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv)); + + byte[] plainText = cipher.doFinal(cText); + + return new String(plainText, UTF_8); + } + + private byte[] getRandomNonce(int numBytes) { + byte[] nonce = new byte[numBytes]; + new SecureRandom().nextBytes(nonce); + + return nonce; + } + + private SecretKey getAESKeyFromPassword(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException { + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + + KeySpec spec = new PBEKeySpec(password, SALT.getBytes(), 65536, 256); + SecretKeySpec secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); + + return secret; + } + + private String hex(byte[] bytes) { + char[] result = Hex.encodeHex(bytes); + return new String(result); + } + + private byte[] unhex(String hex) throws DecoderException { + return Hex.decodeHex(hex.toCharArray()); + } +} diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java new file mode 100644 index 000000000..533537fa1 --- /dev/null +++ b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java @@ -0,0 +1,140 @@ +package com.rjconsultores.ventaboletos.web.utilerias.security; + +import java.text.ParseException; +import java.time.Duration; +import java.util.Calendar; + +import javax.xml.bind.DatatypeConverter; + +import org.apache.log4j.Logger; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.JWSObject; +import com.nimbusds.jose.Payload; +import com.nimbusds.jose.crypto.MACSigner; +import com.nimbusds.jwt.JWTClaimsSet; + +import net.minidev.json.JSONObject; + +public class SecurityEmpresaToken { + private static Logger log = Logger.getLogger(SecurityEmpresaToken.class); + + private String secret = "#KO&Fm4_k.sU9M8`6Mx'F\\\"H:*Qxu]6F4r,)JmZ2Jwafd)I.2[RET'1:)VQ6mG9,"; + private static final Duration ttl = Duration.ofHours(24); + + private Gson gson = new Gson(); + + public String bodyRequestGenerate(final Integer empresaId, final String cnpj) throws SecurityException { + try { + AESGSMHelper crypto = new AESGSMHelper(); + + JsonObject json = new JsonObject(); + json.addProperty("empresaId", empresaId); + json.addProperty("CNPJ", cnpj); + + return crypto.encrypt(json.toString()); + + } catch (Exception e) { + log.error("Erro ao gerar o body usado no request da licença: " + e.getMessage(), e); + + throw new SecurityException(e); + } + } + + public String licenseDefaultGenerate(final Integer empresaId, final String cnpj) throws SecurityException { + try { + AESGSMHelper crypto = new AESGSMHelper(); + + JsonObject json = new JsonObject(); + json.addProperty("empresaId", empresaId); + json.addProperty("CNPJ", cnpj); + json.addProperty("aprovado", 1); + + return crypto.encrypt(json.toString()); + + } catch (Exception e) { + log.error("Erro ao gerar a licença padrão para as empresas existentes: " + e.getMessage(), e); + + throw new SecurityException(e); + } + } + + public boolean licenseValidate(final String license, final Integer empresaId, final String cnpj) { + try { + AESGSMHelper crypto = new AESGSMHelper(); + + final String value = crypto.decrypt(license); + final JsonObject json = gson.fromJson(value, JsonObject.class); + + if (json.has("empresaId") && json.get("empresaId").getAsInt() == empresaId.intValue() + && json.has("CNPJ") && json.get("CNPJ").getAsString().equals(cnpj) + && json.has("aprovado")) { + log.debug("[empresaId=" + json.get("empresaId").getAsString() + ", CNPJ=" + json.get("CNPJ").getAsString() + ", aprovado=" + json.get("aprovado").getAsString() + "]"); + + return json.get("aprovado").getAsString().equals("1"); + } + } catch (Exception e) { + log.error("Erro ao gerar o body usado no request da licença: " + e.getMessage(), e); + } + + return false; + } + + public String requestGenerate(String licenseRequest) throws SecurityException { + return requestGenerate(licenseRequest, ttl); + } + + public String requestGenerate(String licenseRequest, Duration ttl) throws SecurityException { + try { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.MILLISECOND, (int) ttl.toMillis()); + + JWTClaimsSet claims = new JWTClaimsSet.Builder() + .expirationTime(cal.getTime()) + .claim("sub", licenseRequest) + .claim("userId", "adm") + .claim("role", "ROLE_TOKEN") + .build(); + + JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256), new Payload(claims.toJSONObject())); + + jwsObject.sign(new MACSigner(DatatypeConverter.parseBase64Binary(secret))); + + return jwsObject.serialize(); + } catch (Exception e) { + log.error("Erro ao gerar a request: " + e.getMessage(), e); + + throw new SecurityException(e); + } + } + + public String tokenValidate(final String token) throws SecurityException { + try { + JWSObject jwsObject = JWSObject.parse(token); + JSONObject jsonPayload = jwsObject.getPayload().toJSONObject(); + JWTClaimsSet claims = JWTClaimsSet.parse(jsonPayload); + + if (claims.getExpirationTime().compareTo(Calendar.getInstance().getTime()) < 0) { + throw new SecurityException("Token expirado"); + } + + return claims.getSubject(); + + } catch (SecurityException e) { + throw e; + + } catch (ParseException e) { + log.error("Erro no parser do token: " + e.getMessage(), e); + + throw new SecurityException(e); + + } catch (Exception e) { + log.error("Erro ao validar o token: " + e.getMessage(), e); + + throw new SecurityException(e); + } + } +} diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/exception/SecurityException.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/exception/SecurityException.java new file mode 100644 index 000000000..ca6b559f9 --- /dev/null +++ b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/exception/SecurityException.java @@ -0,0 +1,13 @@ +package com.rjconsultores.ventaboletos.web.utilerias.security.exception; + +public class SecurityException extends Exception { + private static final long serialVersionUID = 1801174850577435303L; + + public SecurityException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + public SecurityException(String arg0) { + super(arg0); + } +} diff --git a/tests/com/rjconsultores/tests/SecurityEmpresaTokenTest.java b/tests/com/rjconsultores/tests/SecurityEmpresaTokenTest.java new file mode 100644 index 000000000..82de6e409 --- /dev/null +++ b/tests/com/rjconsultores/tests/SecurityEmpresaTokenTest.java @@ -0,0 +1,91 @@ +package com.rjconsultores.tests; + +import static org.junit.Assert.fail; + +import java.time.Duration; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.rjconsultores.ventaboletos.web.utilerias.security.SecurityEmpresaToken; + +public class SecurityEmpresaTokenTest { + private static final Logger log = LoggerFactory.getLogger(SecurityEmpresaTokenTest.class); + + @Before + public void initApplicationContext() { + log.info("[ BEGIN ]"); + } + + @After + public void closeApplicationContext() { + log.info("[ END ]"); + } + + @Test + public void test_EmpresaNova() throws Exception { + // license request -> token request -> token response -> license + + Integer empresaId = 1313; + String cnpj = "00073778000120"; + + SecurityEmpresaToken security = new SecurityEmpresaToken(); + + final String bodyRequest = security.bodyRequestGenerate(empresaId, cnpj); + final String request = security.requestGenerate(bodyRequest); + + final String license = security.tokenValidate(request); + final boolean valid = security.licenseValidate(license, empresaId, cnpj); + + log.info("Body Request: " + bodyRequest); + log.info("Request: " + request); + log.info("License: " + license); + log.info("Valid: " + Boolean.toString(valid)); + + if (valid) fail("Licença válida"); + } + + @Test + public void test_Licenca() throws Exception { + Integer empresaId = 1313; + String cnpj = "00073778000120"; + + SecurityEmpresaToken security = new SecurityEmpresaToken(); + + final String license = security.licenseDefaultGenerate(empresaId, cnpj); + final boolean valid = security.licenseValidate(license, empresaId, cnpj); + + log.info("License: " + license); + log.info("Valid: " + Boolean.toString(valid)); + + if (!valid) fail("Licença inválida"); + } + + @Test(expected = SecurityException.class) + public void test_TTL_expired() throws Exception { + Duration ttl = Duration.ofSeconds(5); + + Integer empresaId = 1313; + String cnpj = "00073778000120"; + + SecurityEmpresaToken security = new SecurityEmpresaToken(); + + final String bodyRequest = security.bodyRequestGenerate(empresaId, cnpj); + final String request = security.requestGenerate(bodyRequest, ttl); + + Thread.sleep(Duration.ofSeconds(10).toMillis()); + + final String license = security.tokenValidate(request); + final boolean valid = security.licenseValidate(license, empresaId, cnpj); + + log.info("Body Request: " + bodyRequest); + log.info("Request: " + request); + log.info("License: " + license); + log.info("Valid: " + Boolean.toString(valid)); + + if (valid) fail("Licença válida"); + } +} diff --git a/tests/com/rjconsultores/tests/SerieEmbarcadaTest.java b/tests/com/rjconsultores/tests/SerieEmbarcadaTest.java.old similarity index 100% rename from tests/com/rjconsultores/tests/SerieEmbarcadaTest.java rename to tests/com/rjconsultores/tests/SerieEmbarcadaTest.java.old From 61aef7b8cb9a229628018276c3cfffcde55692b3 Mon Sep 17 00:00:00 2001 From: Alberto Trevezani Date: Fri, 3 Nov 2023 18:02:03 -0300 Subject: [PATCH 2/5] =?UTF-8?q?Ajuste=20TTL=20e=20adicionado=20teste=20de?= =?UTF-8?q?=20token=20gerado=20pelo=20servi=C3=A7o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/SecurityEmpresaToken.java | 2 +- .../tests/SecurityEmpresaTokenTest.java | 30 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java index 533537fa1..3fe1f432c 100644 --- a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java +++ b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java @@ -23,7 +23,7 @@ public class SecurityEmpresaToken { private static Logger log = Logger.getLogger(SecurityEmpresaToken.class); private String secret = "#KO&Fm4_k.sU9M8`6Mx'F\\\"H:*Qxu]6F4r,)JmZ2Jwafd)I.2[RET'1:)VQ6mG9,"; - private static final Duration ttl = Duration.ofHours(24); + private static final Duration ttl = Duration.ofDays(7); private Gson gson = new Gson(); diff --git a/tests/com/rjconsultores/tests/SecurityEmpresaTokenTest.java b/tests/com/rjconsultores/tests/SecurityEmpresaTokenTest.java index 82de6e409..ccb6edd43 100644 --- a/tests/com/rjconsultores/tests/SecurityEmpresaTokenTest.java +++ b/tests/com/rjconsultores/tests/SecurityEmpresaTokenTest.java @@ -25,6 +25,31 @@ public class SecurityEmpresaTokenTest { log.info("[ END ]"); } + @Test + public void test_Token() throws Exception { + // license request -> token request -> token response -> license + + Integer empresaId = 1313; + String cnpj = "00073778000120"; + + SecurityEmpresaToken security = new SecurityEmpresaToken(); + + final String bodyRequest = security.bodyRequestGenerate(empresaId, cnpj); + final String request = security.requestGenerate(bodyRequest); + + final String reponse = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI4ZTY2MGVmOTQwMGRlNjU2MmQ1MjljZTVkZDMyZDU0NmM2OGU5YTk0NTUwYjUyNzc4MDhjNWIxMjgzNzkwNjVlNzI0NWU2ZTMxNzBjMTQ2ZGVlOWUyNGQwZjc1YzMwYTVmM2JlYmY5NjY0YzZiNWNiYjU3NTk1NzVmOGYzMTk4OTljNmVmODNkZDc3NmI4YjM2MGM1NDE3N2RhMzFkMDAzNTA5ZDFlIiwiZXhwIjoxNjk5NjQ5OTQ1LCJ1c2VySWQiOiJhZG0iLCJyb2xlIjoiUk9MRV9UT0tFTiJ9.0WFPKf6RcpPYle4Rgq_D-GScwhkw_Q4pmCvNCL_INfg"; + + final String license = security.tokenValidate(reponse); + final boolean valid = security.licenseValidate(license, empresaId, cnpj); + + log.info("Body Request: " + bodyRequest); + log.info("Request: " + request); + log.info("License: " + license); + log.info("Valid: " + Boolean.toString(valid)); + + if (!valid) fail("Licença inválida"); + } + @Test public void test_EmpresaNova() throws Exception { // license request -> token request -> token response -> license @@ -75,14 +100,15 @@ public class SecurityEmpresaTokenTest { final String bodyRequest = security.bodyRequestGenerate(empresaId, cnpj); final String request = security.requestGenerate(bodyRequest, ttl); + + log.info("Body Request: " + bodyRequest); + log.info("Request: " + request); Thread.sleep(Duration.ofSeconds(10).toMillis()); final String license = security.tokenValidate(request); final boolean valid = security.licenseValidate(license, empresaId, cnpj); - log.info("Body Request: " + bodyRequest); - log.info("Request: " + request); log.info("License: " + license); log.info("Valid: " + Boolean.toString(valid)); From 216b878529b7b7f0b93244fa74a64d8e0c0c0725 Mon Sep 17 00:00:00 2001 From: Gleimar Botelho Baleeiro Date: Tue, 14 Nov 2023 17:16:28 -0300 Subject: [PATCH 3/5] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20do=20fluxo=20de?= =?UTF-8?q?=20autoriza=C3=A7=C3=A3o=20para=20novas=20empresas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 +- .../catalogos/EditarEmpresaController.java | 61 +++++++- .../ventaboletos/web/utilerias/MyAppInit.java | 13 ++ .../web/utilerias/security/AESGSMHelper.java | 106 ------------- .../security/SecurityEmpresaToken.java | 140 ------------------ web/WEB-INF/i3-label_pt_BR.label | 5 + web/gui/catalogos/editarEmpresa.zul | 41 +++-- 7 files changed, 110 insertions(+), 260 deletions(-) delete mode 100644 src/java/com/rjconsultores/ventaboletos/web/utilerias/security/AESGSMHelper.java delete mode 100644 src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java diff --git a/pom.xml b/pom.xml index 5220d9f91..28a4d96a2 100644 --- a/pom.xml +++ b/pom.xml @@ -8,8 +8,8 @@ war - 1.18.0 - 1.16.0 + 1.19.1 + 1.17.0 UTF-8 UTF-8 diff --git a/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/catalogos/EditarEmpresaController.java b/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/catalogos/EditarEmpresaController.java index c83b8508f..687a2fa48 100644 --- a/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/catalogos/EditarEmpresaController.java +++ b/src/java/com/rjconsultores/ventaboletos/web/gui/controladores/catalogos/EditarEmpresaController.java @@ -134,6 +134,7 @@ import com.rjconsultores.ventaboletos.web.utilerias.render.RenderComEmpTipoEvent import com.rjconsultores.ventaboletos.web.utilerias.render.RenderEmpresaContaBancaria; import com.rjconsultores.ventaboletos.web.utilerias.render.RenderEmpresaImposto; import com.rjconsultores.ventaboletos.web.utilerias.render.RenderEmpresaInscricaoEstadual; +import com.rjconsultores.ventaboletos.web.utilerias.security.SecurityEmpresaToken; /** * @@ -465,6 +466,12 @@ public class EditarEmpresaController extends MyGenericForwardComposer { private Textbox txtLatitudeLongitude; private Textbox txtLatitude; private Textbox txtLongitude; + + private Textbox txtTokenRJ; + private Textbox txtLicenca; + private Button btnDigitarLicenca; + private Button btnValidarLicenca; + private boolean cadastroEmpresaNova = false; private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; @@ -517,6 +524,8 @@ public class EditarEmpresaController extends MyGenericForwardComposer { if (empresa.getEmpresaId() == null) { btnAdicionarEstadoImposto.setVisible(false); btnAdicionarInscEstadual.setVisible(false); + + cadastroEmpresaNova = true; } else { btnAdicionarEstadoImposto.setVisible(true); @@ -825,6 +834,28 @@ public class EditarEmpresaController extends MyGenericForwardComposer { ajustarRadioAbaRateioComissao(); } + public void onClick$btnDigitarLicenca(Event ev) { + txtLicenca.setDisabled(false); + } + public void onClick$btnValidarLicenca(Event ev) throws InterruptedException { + + String tokenLicensa = empresaService.validarTokenLicensa(empresa,txtLicenca.getText()); + + if (StringUtils.isNotBlank(tokenLicensa)){ + txtLicenca.setText(tokenLicensa); + txtLicenca.setDisabled(true); + btnValidarLicenca.setDisabled(true); + btnDigitarLicenca.setDisabled(true); + empresa.setLicenca(tokenLicensa); + + Messagebox.show(Labels.getLabel("editarEmpresaController.MSG.licencaOK"), + Labels.getLabel("editarEmpresaController.window.title"), Messagebox.OK, Messagebox.INFORMATION); + }else{ + txtLicenca.setText(""); + Messagebox.show(Labels.getLabel("editarEmpresaController.MSG.licencaNOK"), + Labels.getLabel("editarEmpresaController.window.title"), Messagebox.OK, Messagebox.ERROR); + } + } public void onClick$chkAutenticacao(Event ev) { if(chkAutenticacao.isChecked()){ textEmail.setDisabled(false); @@ -899,7 +930,11 @@ public class EditarEmpresaController extends MyGenericForwardComposer { openWindow("/gui/catalogos/editarContaBancariaEmpresa.zul", Labels.getLabel("editarEmpresaController.contaBancaria.window.title"), args, MyGenericForwardComposer.MODAL); } - + + public void onClick$btnGerarToken(Event ev) throws InterruptedException { + txtTokenRJ.setText(empresaService.token(empresa)); + } + public void onClick$btnSalvar(Event ev) throws InterruptedException { txtNome.getValue(); cmbIndTipo.getValue(); @@ -1266,6 +1301,25 @@ public class EditarEmpresaController extends MyGenericForwardComposer { Messagebox.show(Labels.getLabel("editarEmpresaController.MSG.suscribirOK"), Labels.getLabel("editarEmpresaController.window.title"), Messagebox.OK, Messagebox.INFORMATION); + + + + if (cadastroEmpresaNova){ + Messagebox.show( + Labels.getLabel("editarEmpresaController.MSG.tokenNovaEmpresaOK", new String[] {empresa.getToken()}), + Labels.getLabel("editarEmpresaController.window.title"), + Messagebox.OK, Messagebox.EXCLAMATION); + }else{ + + List lsEmpresa = Arrays.asList(new Empresa[]{empresa}); + if (empresaService.filtrarApenasEmpresasLicencaValida(lsEmpresa).isEmpty()){ + Messagebox.show( + Labels.getLabel("editarEmpresaController.MSG.licencaNOK"), + Labels.getLabel("editarEmpresaController.window.title"), + Messagebox.OK, Messagebox.EXCLAMATION); + } + + } closeWindow(); @@ -2854,4 +2908,9 @@ public void onClick$btnTestEmailFlexBus(Event ev) throws InterruptedException { public void setHoraFimEmbarque(Timebox horaFimEmbarque) { this.horaFimEmbarque = horaFimEmbarque; } + + public boolean isExibeDadosTokenLicenca() { + return !cadastroEmpresaNova; + } + } diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/MyAppInit.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/MyAppInit.java index 7b878bf9e..8b206425e 100644 --- a/src/java/com/rjconsultores/ventaboletos/web/utilerias/MyAppInit.java +++ b/src/java/com/rjconsultores/ventaboletos/web/utilerias/MyAppInit.java @@ -29,6 +29,7 @@ import org.zkoss.zk.ui.WebApp; import com.rjconsultores.ventaboletos.FlyWay; import com.rjconsultores.ventaboletos.entidad.Constante; import com.rjconsultores.ventaboletos.service.ConstanteService; +import com.rjconsultores.ventaboletos.service.EmpresaService; import com.rjconsultores.ventaboletos.utilerias.ApplicationProperties; import com.rjconsultores.ventaboletos.web.gui.controladores.job.GeneracionConferenciaMovimentoJob; import com.rjconsultores.ventaboletos.web.gui.controladores.job.GeneracionCorridaJob; @@ -105,6 +106,8 @@ public class MyAppInit implements org.zkoss.zk.ui.util.WebAppInit { customToDatabase(); imageToDatabase(); } + + this.atualizarLicencaPrimeiraVez(); } @@ -434,4 +437,14 @@ public class MyAppInit implements org.zkoss.zk.ui.util.WebAppInit { ConstanteService cs = (ConstanteService) factory.getBean("constanteService"); return cs; } + + private void atualizarLicencaPrimeiraVez(){ + ApplicationContext appContext = AppContext.getApplicationContext(); + BeanFactory factory = (BeanFactory) appContext; + EmpresaService es = (EmpresaService) factory.getBean("empresaService"); + + Integer cantLicencaEmpresasPrimeiraVez = es.atualizarLicencaEmpresasPrimeiraVez(); + + log.info(String.format("cantLicencaEmpresasPrimeiraVez: %s", cantLicencaEmpresasPrimeiraVez)); + } } diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/AESGSMHelper.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/AESGSMHelper.java deleted file mode 100644 index bc7f43653..000000000 --- a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/AESGSMHelper.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.rjconsultores.ventaboletos.web.utilerias.security; - -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.GCMParameterSpec; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Hex; - -public class AESGSMHelper { - private final String SECRET_KEY = "RJ@2019#c0n5ul10r35"; - private final String SALT = "HrqoFr44GtkAhhYN+jP8Ag=="; - private final String ENCRYPT_ALGO = "AES/GCM/NoPadding"; - private final int TAG_LENGTH_BIT = 128; - private final int IV_LENGTH_BYTE = 12; - - private final Charset UTF_8 = StandardCharsets.UTF_8; - - public String encrypt(String value) throws Exception { - SecretKey secret = getAESKeyFromPassword(SECRET_KEY.toCharArray()); - - byte[] pText = value.getBytes(StandardCharsets.UTF_8); - byte[] iv = getRandomNonce(12); - byte[] cipherText = encrypt(pText, secret, iv); - - byte[] cipherTextWithIv = ByteBuffer.allocate(iv.length + cipherText.length) - .put(iv) - .put(cipherText) - .array(); - - return hex(cipherTextWithIv); - } - - private byte[] encrypt(byte[] pText, SecretKey secret, byte[] iv) throws Exception { - Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO); - cipher.init(Cipher.ENCRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv)); - - byte[] encryptedText = cipher.doFinal(pText); - - return encryptedText; - - } - - public String decrypt(String value) throws Exception { - SecretKey secret = getAESKeyFromPassword(SECRET_KEY.toCharArray()); - - byte[] cText = unhex(value); - - ByteBuffer bb = ByteBuffer.wrap(cText); - - byte[] iv = new byte[IV_LENGTH_BYTE]; - bb.get(iv); - - byte[] cipherText = new byte[bb.remaining()]; - bb.get(cipherText); - - String plainText = decrypt(cipherText, secret, iv); - - return plainText; - } - - private String decrypt(byte[] cText, SecretKey secret, byte[] iv) throws Exception { - Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO); - cipher.init(Cipher.DECRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv)); - - byte[] plainText = cipher.doFinal(cText); - - return new String(plainText, UTF_8); - } - - private byte[] getRandomNonce(int numBytes) { - byte[] nonce = new byte[numBytes]; - new SecureRandom().nextBytes(nonce); - - return nonce; - } - - private SecretKey getAESKeyFromPassword(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException { - SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); - - KeySpec spec = new PBEKeySpec(password, SALT.getBytes(), 65536, 256); - SecretKeySpec secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); - - return secret; - } - - private String hex(byte[] bytes) { - char[] result = Hex.encodeHex(bytes); - return new String(result); - } - - private byte[] unhex(String hex) throws DecoderException { - return Hex.decodeHex(hex.toCharArray()); - } -} diff --git a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java b/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java deleted file mode 100644 index 3fe1f432c..000000000 --- a/src/java/com/rjconsultores/ventaboletos/web/utilerias/security/SecurityEmpresaToken.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.rjconsultores.ventaboletos.web.utilerias.security; - -import java.text.ParseException; -import java.time.Duration; -import java.util.Calendar; - -import javax.xml.bind.DatatypeConverter; - -import org.apache.log4j.Logger; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSObject; -import com.nimbusds.jose.Payload; -import com.nimbusds.jose.crypto.MACSigner; -import com.nimbusds.jwt.JWTClaimsSet; - -import net.minidev.json.JSONObject; - -public class SecurityEmpresaToken { - private static Logger log = Logger.getLogger(SecurityEmpresaToken.class); - - private String secret = "#KO&Fm4_k.sU9M8`6Mx'F\\\"H:*Qxu]6F4r,)JmZ2Jwafd)I.2[RET'1:)VQ6mG9,"; - private static final Duration ttl = Duration.ofDays(7); - - private Gson gson = new Gson(); - - public String bodyRequestGenerate(final Integer empresaId, final String cnpj) throws SecurityException { - try { - AESGSMHelper crypto = new AESGSMHelper(); - - JsonObject json = new JsonObject(); - json.addProperty("empresaId", empresaId); - json.addProperty("CNPJ", cnpj); - - return crypto.encrypt(json.toString()); - - } catch (Exception e) { - log.error("Erro ao gerar o body usado no request da licença: " + e.getMessage(), e); - - throw new SecurityException(e); - } - } - - public String licenseDefaultGenerate(final Integer empresaId, final String cnpj) throws SecurityException { - try { - AESGSMHelper crypto = new AESGSMHelper(); - - JsonObject json = new JsonObject(); - json.addProperty("empresaId", empresaId); - json.addProperty("CNPJ", cnpj); - json.addProperty("aprovado", 1); - - return crypto.encrypt(json.toString()); - - } catch (Exception e) { - log.error("Erro ao gerar a licença padrão para as empresas existentes: " + e.getMessage(), e); - - throw new SecurityException(e); - } - } - - public boolean licenseValidate(final String license, final Integer empresaId, final String cnpj) { - try { - AESGSMHelper crypto = new AESGSMHelper(); - - final String value = crypto.decrypt(license); - final JsonObject json = gson.fromJson(value, JsonObject.class); - - if (json.has("empresaId") && json.get("empresaId").getAsInt() == empresaId.intValue() - && json.has("CNPJ") && json.get("CNPJ").getAsString().equals(cnpj) - && json.has("aprovado")) { - log.debug("[empresaId=" + json.get("empresaId").getAsString() + ", CNPJ=" + json.get("CNPJ").getAsString() + ", aprovado=" + json.get("aprovado").getAsString() + "]"); - - return json.get("aprovado").getAsString().equals("1"); - } - } catch (Exception e) { - log.error("Erro ao gerar o body usado no request da licença: " + e.getMessage(), e); - } - - return false; - } - - public String requestGenerate(String licenseRequest) throws SecurityException { - return requestGenerate(licenseRequest, ttl); - } - - public String requestGenerate(String licenseRequest, Duration ttl) throws SecurityException { - try { - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.MILLISECOND, (int) ttl.toMillis()); - - JWTClaimsSet claims = new JWTClaimsSet.Builder() - .expirationTime(cal.getTime()) - .claim("sub", licenseRequest) - .claim("userId", "adm") - .claim("role", "ROLE_TOKEN") - .build(); - - JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256), new Payload(claims.toJSONObject())); - - jwsObject.sign(new MACSigner(DatatypeConverter.parseBase64Binary(secret))); - - return jwsObject.serialize(); - } catch (Exception e) { - log.error("Erro ao gerar a request: " + e.getMessage(), e); - - throw new SecurityException(e); - } - } - - public String tokenValidate(final String token) throws SecurityException { - try { - JWSObject jwsObject = JWSObject.parse(token); - JSONObject jsonPayload = jwsObject.getPayload().toJSONObject(); - JWTClaimsSet claims = JWTClaimsSet.parse(jsonPayload); - - if (claims.getExpirationTime().compareTo(Calendar.getInstance().getTime()) < 0) { - throw new SecurityException("Token expirado"); - } - - return claims.getSubject(); - - } catch (SecurityException e) { - throw e; - - } catch (ParseException e) { - log.error("Erro no parser do token: " + e.getMessage(), e); - - throw new SecurityException(e); - - } catch (Exception e) { - log.error("Erro ao validar o token: " + e.getMessage(), e); - - throw new SecurityException(e); - } - } -} diff --git a/web/WEB-INF/i3-label_pt_BR.label b/web/WEB-INF/i3-label_pt_BR.label index 61b9e8025..1ffc9b013 100644 --- a/web/WEB-INF/i3-label_pt_BR.label +++ b/web/WEB-INF/i3-label_pt_BR.label @@ -1740,6 +1740,9 @@ editarEmpresaController.lbNome.value = Descrição editarEmpresaController.lbConfiguraciones.value = Configurações editarEmpresaController.lbActivo.value = Ativo editarEmpresaController.MSG.suscribirOK = Empresa Registrada com Sucesso. +editarEmpresaController.MSG.tokenNovaEmpresaOK = Para que a Empresa cadastrada possa ser utilizada no sistema, favor acionar o Suporte com o seguinte TOKEN: {0} +editarEmpresaController.MSG.licencaNOK = Licença Informada não é válida. A empresa não ficará disponível para utilização. Favor entrar em contato com o Suporte. +editarEmpresaController.MSG.licencaOK = Licença validada. editarEmpresaController.MSG.borrarPergunta = Deseja Eliminar esta empresa? editarEmpresaController.MSG.borrarOK = Empresa Excluida com Sucesso. editarEmpresaController.MSG.insEstadualCadastrada = Já existe uma inscrição estadual para este estado. @@ -1860,6 +1863,8 @@ editarEmpresaController.cst00.label = CST=00 (Tribuitação Normal) editarEmpresaController.cst40.label = CST=40 (Isento) editarEmpresaController.cst41.label = CST=41 (Não Tributado) editarEmpresaController.codContPrevidencia.label = Código Indicador de Contribuição Previdenciária +editarEmpresaController.tokenEmpresa.label = Token para Licença +editarEmpresaController.tokenLicenca.label = Licença editarEmpresaController.lbInscricaoMunicipal.value =Inscrição Municipal editarEmpresaController.label.isento = ISENTO editarEmpresaController.lbInscricaoMunicipal.label =Insc.Municipal diff --git a/web/gui/catalogos/editarEmpresa.zul b/web/gui/catalogos/editarEmpresa.zul index 8f844a78f..4c50e1b2e 100644 --- a/web/gui/catalogos/editarEmpresa.zul +++ b/web/gui/catalogos/editarEmpresa.zul @@ -166,24 +166,43 @@ - - + + - + + +