Mostrando postagens com marcador Erros. Mostrar todas as postagens
Mostrando postagens com marcador Erros. Mostrar todas as postagens

segunda-feira, 16 de maio de 2022

Erro "Invalid secret key format" ao iniciar o Jboss na migração do Java da Oracle para o OpenJDK

         Neste artigo vou mostrar a solução para o erro java.io.IOException: Invalid secret key format, que ocorre ao usar o Vault do Jboss para armazenar senhas criptografadas. Esse erro ocorre no módulo PicketBox, que é um framework de segurança Java para prover aos desenvolvedores as seguintes funcionalidades:


  • Suporte a autenticação;
  • Suporte a autorização;
  • Suporte a auditoria;
  • Etc.


        Ao usar o OpenJDK o módulo Picketbox não tem acesso ao módulo "sun.jdk", então ele não pode usar a classe "com.sun.crypto.provider.SealedObjectForKeyProtector", ocasionando em um dos erros abaixo: 


Caused by: java.io.IOException: Invalid secret key format
    at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:856)
    at java.security.KeyStore.load(KeyStore.java:1445)
    at org.picketbox.util.KeyStoreUtil.getKeyStore(KeyStoreUtil.java:201)
    at org.picketbox.util.KeyStoreUtil.getKeyStore(KeyStoreUtil.java:151)
    at org.picketbox.plugins.vault.PicketBoxSecurityVault.getKeyStore(PicketBoxSecurityVault.java:688)
    ... 11 more

ou

  Caused by: java.io.IOException: Invalid secret key format
  at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:856)
  at java.security.KeyStore.load(KeyStore.java:1445) [rt.jar:1.8.0_191-1-redhat]
  at org.wildfly.security.credential.store.impl.KeyStoreCredentialStore.load(KeyStoreCredentialStore.java:859) [wildfly-elytron-1.6.1.Final-redhat-00001.jar:1.6.1.Final-redhat-00001]
  ... 11 more

        

        Para corrigir o problema, é necessário adicionar ao PicketBox a dependência ao "sun.jdk", no arquivo %JBOSS_HOME%/modules/system/layers/base/org/picketbox/main/module.xml a seguinte linha:


<module name="sun.jdk"/>


            Pode-se também adicionar um parametro na JVM da seguinte forma:


-Djboss.modules.system.pkgs=org.jboss.byteman,com.sun.crypto.provider           


         Dessa forma, o módulo em questão é carregado e o uso do Vault e criptografia do JBoss funciona normalmente como no JDK da Oracle. A partir da versão 7.1 do JBoss EAP esse problema foi corrigido, a primeira solução que mostrei já vem por padrão. 



Fonte:

https://picketbox.jboss.org/

http://www.mastertheboss.com/jbossas/jboss-security/solving-java-io-ioexception-invalid-secret-key-format/

https://issues.redhat.com/browse/JBEAP-14660

 

segunda-feira, 4 de outubro de 2021

Erro Java 7 usando método split() com String vazia como delimitador

        O método split() do Java recebe como parâmetro uma String ou Regex para dividir a String em um Array de acordo com o delimitador passado. Porém, com o Java 7 (e talvez versões anteriores), quando passado uma String vazia como parâmetro ("") é criado uma posição vazia no início do Array. Nas versões 8 em diante esse problema foi corrigido. A questão é que dependendo do tratamento dado na hora do desenvolvimento, futuramente ao migrar o projeto para uma versão mais atual do Java, vai ter problema.

        

         Basicamente temos duas soluções:

 

  1. Não usar o Split() passando uma String vazia como delimitador, ao invés disso usar uma regex ou fazer um loop pegando as posições do Array.  
  2. Usar um código para atualizar o Array tirando o espaço em branco.

 

         Segue um exemplo de um código que tira o espaço extra no Java 7:

 

//Pega a String e passa para um Array.

String minhaString = "Daniel";

String[] meuArray = minhaString.split("");

       

/*

* Hack para Java 7 pq inclui uma posição vazia no inicio do array após o split na String.

* A partir da versão 8 do Java o problema não existe mais.

*/

if(meuArray[0].equals("")){

     String[] hack = new String[meuArray.length-1];

     System.arraycopy(meuArray, 1, hack, 0, hack.length);

     meuArray = hack;

}

/*Fim do hack*/

 

         Eu prefiro usar a opção 1, mas há casos em que a opção 2 pode ajudar, vai depender de cada situação.

quinta-feira, 23 de setembro de 2021

Configurando repositório HTTPS para o Maven (Erro: Failed to read artifact ... from/to central) (Erro 501)

        As vezes estamos trabalhando em projetos antigos com versões legadas do Java e consecutivamente do Eclipse, e podemos nos deparar com um problema ao usar o Maven. Ao tentar baixar as dependências do projeto, a versão do Maven do eclipse pode dar um erro pois ela tenta usar o endereço  http://repo.maven.apache.org/maven2/ que está em desuso. Ao colocar essa URL no navegador e tentar acessar recebemos o erro 501 e uma mensagem para acessar o endereço HTTPS: https://repo.maven.apache.org/maven2/.


       Podemos fazer isso criando apontando para um mirror usando o arquivo de configuração settings.xml que caso não exista, pode ser criado na pasta .m2 do usuário no seu S.O. Caso exista o arquivo, basta acrescentar o código referente aos mirrors.


        Segue o código do arquivo settings.xml abaixo:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<settings

  xmlns="http://maven.apache.org/SETTINGS/1.0.0"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 

  http://maven.apache.org/xsd/settings-1.0.0.xsd">

  

 <offline>false</offline>


 <mirrors>

    <mirror>

        <id>Maven</id>

<name>Central Repository</name>

        <url>https://repo.maven.apache.org/maven2/</url>

        <mirrorOf>central</mirrorOf>

     </mirror>

  </mirrors>

</settings>


       Para esse artigo é só, espero ter ajudado.

terça-feira, 11 de maio de 2021

Erro ao Criar Runner Gitlab no Docker Toolbox - Error response from daemon: invalid mode: \MinGW\msys\1.0\etc\gitlab-runner.

      Nesse post eu mostro como resolver um problema de criar um Runner do Gitlab para quem usa o Docker Toolbox. Sabe o que é o Docker Toolbox? Um projeto (que até foi descontinuado, porém eu uso devido a problemas que tive com o Docker rodando direto na minha máquia e outras coisas que uso) que instala as ferramentas Docker (Docker Engine, Docker Machine, etc)  dentro de uma "caixa" que abstrai as características da sua máquina e roda o Docker independentemente delas. Como tudo no mundo, isso tem vantagens e desvantagens. Como o Docker Toolbox roda dentro dessa "caixa" algumas coisas funcionam um pouco diferentes. Os volumes são uma delas.

     Após baixar a imagem do Runner com o comando:


$ docker pull gitlab/gitlab-runner:latest


     Quando vamos executar o comando que sobe  o Runner criando os volumes:


$   docker run -d --name gitlab-runner --restart always -v /Users/Shared/gitlab-runner/config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest


     Recebemos o seguinte erro:


c:\Program Files\Docker Toolbox\docker.exe: Error response from daemon: invalid mode: \MinGW\msys\1.0\etc\gitlab-runner. 

See 'c:\Program Files\Docker Toolbox\docker.exe run --help'.


     E procurando a solução, encontrei e foi bem simples, basta adicionar uma barra "/" a mais no início dos caminhos do volume, ficando assim:


$ docker run -d --name gitlab-runner --restart always -v //Users/Shared/gitlab-runner/config://etc/gitlab-runner -v //var/run/docker.sock://var/run/docker.sock gitlab/gitlab-runner:latest 


     Pronto. Agora funciona tranquilo.


https://stackoverflow.com/questions/50540721/docker-toolbox-error-response-from-daemon-invalid-mode-root-docker

quinta-feira, 5 de novembro de 2020

Erro VT-x is not available (verr_vmx_no_vmx)

             Hoje vou trazer uma solução para um erro que me deu um trabalhão para encontrar uma solução, o erro VT-x is not available (verr_vmx_no_vmx).

         

          Passei por este erro ao instalar o Docker-Machine na minha máquina com Windows 10 e o VirtualBox, resultando que nenhum dos dois funcionou mais.

 

          1 - Vamos entender o problema:

 

VT-x é a Tecnologia de Virtualização da Intel que permite o processador rodar varios SOs ao mesmo tempo de forma que eles “achem” que estão rodando de forma independente. (tem link sobre isso no final).

 

Bem, até aí, tudo normal, você pode instalar VirtualBox por exemplo e mandar ver. A questão é quando você instala algum programa ou usa alguma funcionalidade que usa o Hyper-v no Windows 10 ele simplesmente “toma” o driver VT-x pra ele e não divide com outros programas, assim, o VirtualBox, por exemplo, para de funcionar. E geralmente habilitamos o Hyper-v pra trabalhar com o Docker. Isso quer dizer que as duas tecnologias Docker podem gerar incompatibilidade entre si dependendo da forma que usadas no Windows.

 

          O que é o Hyper-v? É o sistema de virtualização nativo do Windows 10. (link no final).

 

2 – Solução:

 

Para o caso de o problema ter sido gerado pelo uso do Docker-Machine você pode usar o driver Hyper-v ao invés do VirtualBox para criar as VMs. Veja como aqui: https://docs.docker.com/machine/drivers/hyper-v/

 

Para outros casos, ou quando quiser forçar o uso do VirtualBox com o Docker-Machine você vai precisar ficar habilitando e desabilitando o Hyper-v pela linha de comando e também na tela de ativação/desativação de recursos do windows, e vai precisar reiniciar ao fazer isso.

 

          Com esse comando você desabilita:

 

> bcdedit /set hypervisorlaunchtype off

         

          Com esse você habilita:

 

> bcdedit /set hypervisorlaunchtype on 

ou

bcdedit /set hypervisorlaunchtype auto


          E depois na tela de recursos do Windows você também habilita/desabilita:




 

          !IMPORTANTE! O Docker está dando a opção de usar o Windows Subsystem Linux - WSL 2 no lugar do Hyper-v, mas essa solução continua usando o Hyper-v por baixo dos panos, veja no link https://docs.docker.com/docker-for-windows/wsl/Por hoje é isso, espero ter ajudado!

 

Links:

https://www.clubedohardware.com.br/artigos/processadores/tudo-o-que-voc%C3%AA-precisa-saber-sobre-a-tecnologia-de-virtualiza%C3%A7%C3%A3o-da-intel-r34579/

 

https://docs.microsoft.com/pt-br/virtualization/hyper-v-on-windows/about/

 

https://docs.microsoft.com/en-us/archive/blogs/gmarchetti/turning-hyper-v-on-and-off

terça-feira, 25 de agosto de 2020

JPA - Carregando multiplas listas em uma mesma entidade evitando o erro MultipleBagFetchException

    É comum termos um entidade que precise carregar mais de uma lista, e quando essas listas precisam ser carregadas juntas no mesmo select, podemos nos deparar com o seguinte erro:
 
Caused by: org.hibernate.loader.MultipleBagFetchException: 
cannot simultaneously fetch multiple bags

    Bag significa algo como "bolsa" ou "sacola" (tradução livre rsrsrs), e isso quer dizer estamos tentando carregar mais de uma "bolsa" de dados e o JPA não sabe como organizar esses dados para nos entregar.

    Isso ocorre porque geralmente o banco nos devolve uma lista ordenada de dados (List), mas como o JPA está tentando montar uma lista que contém listas dentro delas, ele pode acabar desordenando essas listas. Então ele quer que você diga pra ele como tratar esses dados.

    Existem basicamente 3 formas de contornarmos esse problema:

  1. Nunca carregar as listas na mesma consulta.
  2. Usar Set ao invés de List ao criar as listas na entidade.
  3. Usando a anotação @OrderColumn.
   Vamos abordar cada uma delas a seguir:

    1 - Nunca carregar as listas na mesma consulta.

    Ao invés de você usar o FetchType.EAGER ou no select fazer um join fetch caso o carregamento seja FetchType.LAZY nas "n" listas da sua entidade, você carrega apenas uma delas no primeiro momento, e a(s) outra(s) você carrega separadamente, por exemplo chamando o método get da(s) outra(s) lista(s) com o objeto ainda gerenciado pelo JPA, de forma que ele vá ao banco e preencha essas listas.
     
    2 - Usar Set ao invés de List ao criar as listas na entidade.

    Outra solução é usar o Set ao invés do List. Como o Set não é ordenado como o List o JPA não vai se perder tentando ordenar essa lista. Lembrando que o Set não trabalha com dados duplicados.

    3 - Usando a anotação @OrderColumn.

    Você também pode criar um campo para o hibernate trabalhar a ordenação e não se perder. A desvantagem dessa solução é unicamente a de criar um campo extra para o JPA poder ordenar os dados. 

    Se o mapeamento for bidirecional, será preciso criar a propriedade e mapea-la na classe que detêm o mapeamento além de usá-la no @orderColumn.
    
@Entity
public class Paciente {
 
    //se tiver o mappedBy (bidirecional) precisa criar a propriedade na outra classe 
    @OneToMany(mappedBy="paciente")
    @OrderColumn(name="ordenacao_hibernate")
    private List<PacienteSintoma> lstPacienteSintoma;
 
    //se tiver o mappedBy (bidirecional) precisa criar a propriedade na outra classe 
    @OneToMany(mappedBy="paciente")
    @OrderColumn(name="ordenacao_hibernate")
    private List<PacienteDiagnostico> lstPacienteDiagnostico; 
 
    ...
}

@Entity
public class PacienteSintoma {
    ...
    //bidirecional, necessário mapear a propriedade
    @Column(name="ordenacao_hibernate")
    private int ordenacaoHibernate;

    @ManyToOne
    @JoinColumn(name="paciente_id", nullable=false)
    private Paciente  paciente;
 
    ...
}
 
@Entity
public class PacienteDiagnostico {
    ...
    //bidirecional, necessário mapear a propriedade
    @Column(name="ordenacao_hibernate")
    private int ordenacaoHibernate;

    @ManyToOne
    @JoinColumn(name="paciente_id", nullable=false)
    private Paciente  paciente;
 
    ...
} 
 
    Se o mapeamento for unidirecional, será preciso criar apenas o campo no banco e passá-lo no @orderColumn.

@Entity
public class Paciente {
 
    //unidirecional 
    @OneToMany
    @JoinColumn(name="paciente_id", nullable=false) 
    @OrderColumn(name="ordenacao_hibernate")
    private List<PacienteSintoma> lstPacienteSintoma;
 
    //se tiver o mappedBy (bidirecional) precisa criar a propriedade na outra classe 
    @OneToMany(mappedBy="paciente")
    @JoinColumn(name="paciente_id", nullable=false)  
    @OrderColumn(name="ordenacao_hibernate")
    private List<PacienteDiagnostico> lstPacienteDiagnostico; 
 
    ...
}

@Entity
public class PacienteSintoma {
    ...
    //bidirecional, necessário mapear a propriedade
    @Column(name="ordenacao_hibernate")
    private int ordenacaoHibernate;

    @ManyToOne
    @JoinColumn(name="paciente_id", nullable=false, insertable=false, updatable=false)
    private Paciente  paciente;
 
    ...
}
 
@Entity
public class PacienteDiagnostico {
    ...
    //bidirecional, necessário mapear a propriedade
    @Column(name="ordenacao_hibernate")
    private int ordenacaoHibernate;

    @ManyToOne
    @JoinColumn(name="paciente_id", nullable=false, insertable=false, updatable=false)
    private Paciente  paciente;
 
    ...
} 
Fonte: https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#entity-hibspec-collection-extratype-indexbidir


 

sexta-feira, 17 de julho de 2020

Resolvendo problema CORS no Spring

Olá, hoje vou falar sobre o CORS – Cross-Origin Resource Sharing que significa compartilhamento de recursos de origem cruzada.

Antes era muito comum o uso de iFrames ou similares para fazer com que um site acessasse diretamente conteúdo de outros o que também era válido para aplicações web mais complexas, o problema é que isso começou a ser explorado por pessoas mal intencionadas para se passarem por um site ou serviço que não são e roubar informações ou outras atividades ilícitas. Então os navegadores começaram a “bloquear” esse tipo de coisa, validando antes se a origem tem acesso ao backend vindo de um IP diferente ou não configurado em uma digamos “White list”.

         Trarar o CORS é obrigação do backend, e vamos ver como fazer isso no Spring. No caso, podemos fazer de duas formas: liberando geral ou especificando as URLs que terão o acesso garantido.

    Para liberar qualquer endereço, podemos desabilitar o CORS na classe de configuração de segurança:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests().antMatchers("/xxx/**").authenticated();
        http.authorizeRequests().anyRequest().permitAll();
        http.csrf().disable();

    }

}


        Ou podemos criar um bean na classe principal da aplicação e passar o padrão de URL como "/**":
       
@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");
        }
    };
}


    Para liberar endereços específicos, o que é mais recomendado, basta passar o endereço no lugar do "/**":

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");
        }
    };
}


     Outra forma de fazer é ao invés de criar o bean na classe principal, é criar uma classe específica com a configuração, deixando-a mais explícita:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class CorsConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }

}

 



 FOnte: https://spring.io/guides/gs/rest-service-cors/ 

sexta-feira, 8 de maio de 2020

Evitando o erro: sun.awt.X11GraphicsEnvironment


Para evitar problemas com aplicações Java rodando em servidores Linux sem modo gráfico disponível, é sempre bom usar o parâmetro:

-Djava.awt.headless=true

Isso vai evitar que em algum momento você se depare com um erro no servidor e gaste um bom tempo até se lembrar desse problema. E qual o problema que esse parâmetro evita?

Bom, você pode diretamente usar alguma classe do pacote sun.aws ou alguma biblioteca que use classes desse pacote (como o IReport, etc), e o problema é que esse pacote trabalha com algumas coisas que precisam ser renderizadas e tenta usar bibliotecas que se comunicam com a interface gráfica do servidor pra isso, e ao serem usadas suas classes ele verifica se o servidor tem modo gráfico disponível ou não, caso não, ele lança uma exceção.

Provavelmente a exceção vai ter algo a ver com sun.awt.X11GraphicsEnvironment

O parâmetro indicado acima a grosso modo diz ao Java pra ignorar o uso das bibliotecas do modo gráfico do servidor.

Então esse é um bom parâmetro pra usar sempre.  



Fonte:
http://www.jguru.com/faq/view.jsp?EID=222296

sábado, 27 de julho de 2019

Resolvendo problema CORS no Angular

Olá, hoje vou falar sobre o CORS – Cross-Origin Resource Sharing que significa compartilhamento de recursos de origem cruzada.

Antes era muito comum o uso de iFrames ou similares para fazer com que um site acessasse diretamente conteúdo de outros o que também era válido para aplicações web mais complexas, o problema é que isso começou a ser explorado por pessoas mal intencionadas para se passarem por um site ou serviço que não são e roubar informações ou outras atividades ilícitas. Então os navegadores começaram a “bloquear” esse tipo de coisa, validando antes se a origem tem acesso ao backend vindo de um IP diferente ou não configurado em uma digamos “White list”.

Trarar o CORS é obrigação do backend ou infra, mas é possível e também uma boa prática tratar no frontend. Para isso criamos um Proxy no nosso frontend. Como funciona um proxy? Ele recebe a requisição e a repassa com uma nova configuração de rede.

Vamos criar o nosso proxy, crie um arquivo chamado proxy.config.js no mesmo diretório em que se encontra o seu package.json  com o seguinte conteúdo:

{
"/api": {
    "target": "http://localhost:8080", //endereço do backend
    "secure": false
}
}
Agora configure dentro do seu angular.json o uso do proxy:
...
"defaults"
:{
     "serve":{
          "proxyConfig":"./proxy.config.js"
      }
...


Fonte:
Para ver todas as opções da configuração de proxy veja:
https://webpack.js.org/configuration/dev-server/#devserver-proxy